diff --git a/session/private.go b/session/private.go new file mode 100644 index 00000000..4d4f3c20 --- /dev/null +++ b/session/private.go @@ -0,0 +1,37 @@ +package session + +import ( + "crypto/ecdsa" + "crypto/rand" + + crypto "github.com/nspcc-dev/neofs-crypto" +) + +type pToken struct { + // private session token + sessionKey *ecdsa.PrivateKey +} + +// NewSessionPrivateToken creates PrivateToken instance. +// +// Returns non-nil error on key generation error. +func NewPrivateToken() (PrivateToken, error) { + sk, err := ecdsa.GenerateKey(defaultCurve(), rand.Reader) + if err != nil { + return nil, err + } + + return &pToken{ + sessionKey: sk, + }, nil +} + +// Sign signs data with session private key. +func (t *pToken) Sign(data []byte) ([]byte, error) { + return crypto.Sign(t.sessionKey, data) +} + +// PublicKey returns a binary representation of the session public key. +func (t *pToken) PublicKey() []byte { + return crypto.MarshalPublicKey(&t.sessionKey.PublicKey) +} diff --git a/session/private_test.go b/session/private_test.go new file mode 100644 index 00000000..f0fb9f4e --- /dev/null +++ b/session/private_test.go @@ -0,0 +1,33 @@ +package session + +import ( + "crypto/rand" + "testing" + + crypto "github.com/nspcc-dev/neofs-crypto" + "github.com/stretchr/testify/require" +) + +func TestPrivateToken(t *testing.T) { + // create new private token + pToken, err := NewPrivateToken() + require.NoError(t, err) + + // generate data to sign + data := make([]byte, 10) + _, err = rand.Read(data) + require.NoError(t, err) + + // sign data via private token + sig, err := pToken.Sign(data) + require.NoError(t, err) + + // check signature + require.NoError(t, + crypto.Verify( + crypto.UnmarshalPublicKey(pToken.PublicKey()), + data, + sig, + ), + ) +} diff --git a/session/service.go b/session/service.go index 367aeb13..915abb4b 100644 --- a/session/service.go +++ b/session/service.go @@ -17,10 +17,10 @@ type ( // TokenStore is a PToken storage manipulation interface. TokenStore interface { // New returns new token with specified parameters. - New(p TokenParams) *PToken + New(p TokenParams) PrivateToken // Fetch tries to fetch a token with specified id. - Fetch(id TokenID) *PToken + Fetch(id TokenID) PrivateToken // Remove removes token with id from store. Remove(id TokenID) diff --git a/session/store.go b/session/store.go index 7c56c39a..440fbb56 100644 --- a/session/store.go +++ b/session/store.go @@ -13,7 +13,7 @@ import ( type simpleStore struct { *sync.RWMutex - tokens map[TokenID]*PToken + tokens map[TokenID]PrivateToken } // TODO get curve from neofs-crypto @@ -25,12 +25,12 @@ func defaultCurve() elliptic.Curve { func NewSimpleStore() TokenStore { return &simpleStore{ RWMutex: new(sync.RWMutex), - tokens: make(map[TokenID]*PToken), + tokens: make(map[TokenID]PrivateToken), } } // New returns new token with specified parameters. -func (s *simpleStore) New(p TokenParams) *PToken { +func (s *simpleStore) New(p TokenParams) PrivateToken { tid, err := refs.NewUUID() if err != nil { return nil @@ -54,10 +54,8 @@ func (s *simpleStore) New(p TokenParams) *PToken { token.SetExpirationEpoch(p.LastEpoch) token.SetSessionKey(crypto.MarshalPublicKey(&key.PublicKey)) - t := &PToken{ - mtx: new(sync.Mutex), - Token: *token, - PrivateKey: key, + t := &pToken{ + sessionKey: key, } s.Lock() @@ -68,7 +66,7 @@ func (s *simpleStore) New(p TokenParams) *PToken { } // Fetch tries to fetch a token with specified id. -func (s *simpleStore) Fetch(id TokenID) *PToken { +func (s *simpleStore) Fetch(id TokenID) PrivateToken { s.RLock() defer s.RUnlock() diff --git a/session/types.go b/session/types.go index e56373cf..e7e4b2a3 100644 --- a/session/types.go +++ b/session/types.go @@ -1,13 +1,9 @@ package session import ( - "crypto/ecdsa" - "sync" - "github.com/nspcc-dev/neofs-api-go/internal" "github.com/nspcc-dev/neofs-api-go/refs" "github.com/nspcc-dev/neofs-api-go/service" - crypto "github.com/nspcc-dev/neofs-crypto" ) type ( @@ -23,17 +19,20 @@ type ( Address = refs.Address // Verb is Token_Info_Verb type alias Verb = service.Token_Info_Verb - - // PToken is a wrapper around Token that allows to sign data - // and to do thread-safe manipulations. - PToken struct { - Token - - mtx *sync.Mutex - PrivateKey *ecdsa.PrivateKey - } ) +// PrivateToken is an interface of session private part. +type PrivateToken interface { + // PublicKey must return a binary representation of session public key. + PublicKey() []byte + + // Sign must return the signature of passed data. + // + // Resulting signature must be verified by crypto.Verify function + // with the session public key. + Sign([]byte) ([]byte, error) +} + const ( // ErrWrongFirstEpoch is raised when passed Token contains wrong first epoch. // First epoch is an epoch since token is valid @@ -58,8 +57,3 @@ const ( // ErrInvalidSignature is raised when wrong signature is passed to VerificationHeader.VerifyData(). ErrInvalidSignature = internal.Error("invalid signature") ) - -// SignData signs data with session private key. -func (t *PToken) SignData(data []byte) ([]byte, error) { - return crypto.Sign(t.PrivateKey, data) -}