diff --git a/docs/session.md b/docs/session.md index e8633d3..ba615c3 100644 --- a/docs/session.md +++ b/docs/session.md @@ -115,6 +115,7 @@ User token granting rights for object manipulation | ObjectID | [bytes](#bytes) | repeated | ObjectID is an object identifier of manipulation object | | Signature | [bytes](#bytes) | | Signature is a token signature, signed by owner of manipulation object | | ID | [bytes](#bytes) | | ID is a token identifier. valid UUIDv4 represented in bytes | +| PublicKeys | [bytes](#bytes) | repeated | PublicKeys associated with owner | diff --git a/session/store_test.go b/session/store_test.go index 1a9e977..66f99d4 100644 --- a/session/store_test.go +++ b/session/store_test.go @@ -31,20 +31,22 @@ func newTestClient(t *testing.T) *testClient { func signToken(t *testing.T, token *PToken, c *testClient) { require.NotNil(t, token) + token.SetPublicKeys(&c.PublicKey) signH, err := c.Sign(token.Header.PublicKey) require.NoError(t, err) require.NotNil(t, signH) // data is not yet signed - require.False(t, token.Verify(&c.PublicKey)) + keys := UnmarshalPublicKeys(&token.Token) + require.False(t, token.Verify(keys...)) signT, err := c.Sign(token.verificationData()) require.NoError(t, err) require.NotNil(t, signT) token.AddSignatures(signH, signT) - require.True(t, token.Verify(&c.PublicKey)) + require.True(t, token.Verify(keys...)) } func TestTokenStore(t *testing.T) { diff --git a/session/types.go b/session/types.go index aff7cca..08abec8 100644 --- a/session/types.go +++ b/session/types.go @@ -6,6 +6,7 @@ import ( "sync" crypto "github.com/nspcc-dev/neofs-crypto" + "github.com/nspcc-dev/neofs-proto/chain" "github.com/nspcc-dev/neofs-proto/internal" "github.com/nspcc-dev/neofs-proto/refs" "github.com/pkg/errors" @@ -111,11 +112,24 @@ func (m *Token) Sign(key *ecdsa.PrivateKey) error { return nil } +// SetPublicKeys sets owner's public keys to the token +func (m *Token) SetPublicKeys(keys... *ecdsa.PublicKey) { + m.PublicKeys = m.PublicKeys[:0] + for i := range keys { + m.PublicKeys = append(m.PublicKeys, crypto.MarshalPublicKey(keys[i])) + } +} + // Verify checks if token is correct and signed. func (m *Token) Verify(keys ...*ecdsa.PublicKey) bool { if m.FirstEpoch > m.LastEpoch { return false } + ownerFromKeys := chain.KeysToAddress(keys...) + if m.OwnerID.String() != ownerFromKeys { + return false + } + for i := range keys { if m.Header.Verify(keys[i]) && crypto.Verify(keys[i], m.verificationData(), m.Signature) == nil { return true @@ -156,3 +170,12 @@ func (m *VerificationHeader) Verify(keys ...*ecdsa.PublicKey) bool { } return false } + +// UnmarshalPublicKeys returns unmarshal public keys from the token +func UnmarshalPublicKeys(t *Token) []*ecdsa.PublicKey { + r := make([]*ecdsa.PublicKey, 0, len(t.PublicKeys)) + for i := range t.PublicKeys { + r = append(r, crypto.UnmarshalPublicKey(t.PublicKeys[i])) + } + return r +} diff --git a/session/types.pb.go b/session/types.pb.go index f597612..5b2f5c4 100644 Binary files a/session/types.pb.go and b/session/types.pb.go differ diff --git a/session/types.proto b/session/types.proto index 1ade791..294928b 100644 --- a/session/types.proto +++ b/session/types.proto @@ -29,4 +29,6 @@ message Token { bytes Signature = 6; // ID is a token identifier. valid UUIDv4 represented in bytes bytes ID = 7 [(gogoproto.customtype) = "TokenID", (gogoproto.nullable) = false]; + // PublicKeys associated with owner + repeated bytes PublicKeys = 8; }