From c37e0393600a129ffd5efe302d122d884420e6e0 Mon Sep 17 00:00:00 2001 From: Dmitry Bilienko Date: Wed, 12 Apr 2023 13:23:33 +0500 Subject: [PATCH 1/4] Check all payload validations on nodes --- commonspace/spacestorage/spacestorage.go | 107 +++- commonspace/spacestorage/spacestorage_test.go | 472 ++++++++++++++++++ 2 files changed, 578 insertions(+), 1 deletion(-) create mode 100644 commonspace/spacestorage/spacestorage_test.go diff --git a/commonspace/spacestorage/spacestorage.go b/commonspace/spacestorage/spacestorage.go index 8d300a48..af4ab7e5 100644 --- a/commonspace/spacestorage/spacestorage.go +++ b/commonspace/spacestorage/spacestorage.go @@ -2,8 +2,10 @@ package spacestorage import ( + "bytes" "context" "errors" + "fmt" "github.com/anytypeio/any-sync/app" "github.com/anytypeio/any-sync/commonspace/object/acl/aclrecordproto" "github.com/anytypeio/any-sync/commonspace/object/acl/liststorage" @@ -14,6 +16,7 @@ import ( "github.com/anytypeio/any-sync/util/cidutil" "github.com/anytypeio/any-sync/util/crypto" "github.com/gogo/protobuf/proto" + "strconv" "strings" ) @@ -66,10 +69,112 @@ type SpaceStorageProvider interface { } func ValidateSpaceStorageCreatePayload(payload SpaceStorageCreatePayload) (err error) { - // TODO: add proper validation + err = validateCreateSpaceHeaderPayload(payload.SpaceHeaderWithId) + if err != nil { + return + } + err = validateCreateSpaceAclPayload(payload.AclWithId) + if err != nil { + return + } + err = validateCreateSpaceSettingsPayload(payload.SpaceSettingsWithId) + if err != nil { + return + } + return nil } +func validateCreateSpaceHeaderPayload(rawHeaderWithId *spacesyncproto.RawSpaceHeaderWithId) (err error) { + var rawSpaceHeader spacesyncproto.RawSpaceHeader + err = proto.Unmarshal(rawHeaderWithId.RawHeader, &rawSpaceHeader) + if err != nil { + return + } + var header spacesyncproto.SpaceHeader + err = proto.Unmarshal(rawSpaceHeader.SpaceHeader, &header) + if err != nil { + return + } + + split := strings.Split(rawHeaderWithId.Id, ".") + if len(split) != 2 { + return ErrIncorrectSpaceHeader + } + if !cidutil.VerifyCid(rawSpaceHeader.SpaceHeader, split[0]) { + err = objecttree.ErrIncorrectCid + return + } + payloadIdentity, err := crypto.UnmarshalEd25519PublicKeyProto(header.Identity) + res, err := payloadIdentity.Verify(rawSpaceHeader.SpaceHeader, rawSpaceHeader.Signature) + if err != nil || !res { + err = ErrIncorrectSpaceHeader + return + } + + id, err := cidutil.NewCidFromBytes(rawSpaceHeader.SpaceHeader) + requiredSpaceId := fmt.Sprintf("%s.%s", id, strconv.FormatUint(header.ReplicationKey, 36)) + if requiredSpaceId != rawHeaderWithId.Id { + err = ErrIncorrectSpaceHeader + return + } + + return +} + +func validateCreateSpaceAclPayload(rawWithId *aclrecordproto.RawAclRecordWithId) (err error) { + if !cidutil.VerifyCid(rawWithId.Payload, rawWithId.Id) { + err = objecttree.ErrIncorrectCid + return + } + var rawAcl aclrecordproto.RawAclRecord + err = proto.Unmarshal(rawWithId.Payload, &rawAcl) + if err != nil { + return + } + var aclRoot aclrecordproto.AclRoot + err = proto.Unmarshal(rawAcl.Payload, &aclRoot) + payloadIdentity, err := crypto.UnmarshalEd25519PublicKeyProto(aclRoot.Identity) + res, err := payloadIdentity.Verify(rawAcl.Payload, rawAcl.Signature) + if err != nil || !res { + err = ErrIncorrectSpaceHeader + return + } + masterKey, err := crypto.UnmarshalEd25519PrivateKey(aclRoot.MasterKey) + identity, err := crypto.UnmarshalEd25519PublicKeyProto(aclRoot.Identity) + rawIdentity, err := identity.Raw() + signedIdentity, err := masterKey.Sign(rawIdentity) + if !bytes.Equal(signedIdentity, aclRoot.IdentitySignature) { + err = ErrIncorrectSpaceHeader + return + } + return +} + +func validateCreateSpaceSettingsPayload(rawWithId *treechangeproto.RawTreeChangeWithId) (err error) { + var raw treechangeproto.RawTreeChange + err = proto.Unmarshal(rawWithId.RawChange, &raw) + if err != nil { + return + } + var rootChange treechangeproto.RootChange + err = proto.Unmarshal(raw.Payload, &rootChange) + payloadIdentity, err := crypto.UnmarshalEd25519PublicKeyProto(rootChange.Identity) + res, err := payloadIdentity.Verify(raw.Payload, raw.Signature) + if err != nil || !res { + err = ErrIncorrectSpaceHeader + return + } + id, err := cidutil.NewCidFromBytes(rawWithId.RawChange) + if id != rawWithId.Id { + err = ErrIncorrectSpaceHeader + return + } + + return +} + +// ValidateSpaceHeader Used in coordinator func ValidateSpaceHeader(spaceId string, header []byte, identity crypto.PubKey) (err error) { split := strings.Split(spaceId, ".") if len(split) != 2 { diff --git a/commonspace/spacestorage/spacestorage_test.go b/commonspace/spacestorage/spacestorage_test.go new file mode 100644 index 00000000..2eabb66f --- /dev/null +++ b/commonspace/spacestorage/spacestorage_test.go @@ -0,0 +1,472 @@ +package spacestorage + +import ( + "crypto/rand" + "fmt" + "github.com/anytypeio/any-sync/commonspace/object/accountdata" + "github.com/anytypeio/any-sync/commonspace/object/acl/aclrecordproto" + "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree" + "github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto" + "github.com/anytypeio/any-sync/commonspace/spacesyncproto" + "github.com/anytypeio/any-sync/util/cidutil" + "github.com/anytypeio/any-sync/util/crypto" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + rand2 "golang.org/x/exp/rand" + "strconv" + "testing" + "time" +) + +func TestSuccessHeaderPayloadForSpaceCreate(t *testing.T) { + accountKeys, err := accountdata.NewRandom() + require.NoError(t, err) + identity, err := accountKeys.SignKey.GetPublic().Marshall() + require.NoError(t, err) + spaceHeaderSeed := make([]byte, 32) + _, err = rand.Read(spaceHeaderSeed) + require.NoError(t, err) + spaceHeaderPayload := make([]byte, 32) + _, err = rand.Read(spaceHeaderPayload) + require.NoError(t, err) + replicationKey := rand2.Uint64() + header := &spacesyncproto.SpaceHeader{ + Identity: identity, + Timestamp: time.Now().Unix(), + SpaceType: "SpaceType", + ReplicationKey: replicationKey, + Seed: spaceHeaderSeed, + SpaceHeaderPayload: spaceHeaderPayload, + } + marhalled, err := header.Marshal() + require.NoError(t, err) + signature, err := accountKeys.SignKey.Sign(marhalled) + require.NoError(t, err) + rawHeader := &spacesyncproto.RawSpaceHeader{ + SpaceHeader: marhalled, + Signature: signature, + } + marhalledRawHeader, err := rawHeader.Marshal() + require.NoError(t, err) + id, err := cidutil.NewCidFromBytes(marhalled) + require.NoError(t, err) + spaceId := fmt.Sprintf("%s.%s", id, strconv.FormatUint(replicationKey, 36)) + rawHeaderWithId := &spacesyncproto.RawSpaceHeaderWithId{ + RawHeader: marhalledRawHeader, + Id: spaceId, + } + err = validateCreateSpaceHeaderPayload(rawHeaderWithId) + require.NoError(t, err) +} + +func TestFailedHeaderPayloadForSpaceCreate_InvalidFormatSpaceId(t *testing.T) { + accountKeys, err := accountdata.NewRandom() + require.NoError(t, err) + identity, err := accountKeys.SignKey.GetPublic().Marshall() + require.NoError(t, err) + spaceHeaderSeed := make([]byte, 32) + _, err = rand.Read(spaceHeaderSeed) + require.NoError(t, err) + spaceHeaderPayload := make([]byte, 32) + _, err = rand.Read(spaceHeaderPayload) + require.NoError(t, err) + replicationKey := rand2.Uint64() + header := &spacesyncproto.SpaceHeader{ + Identity: identity, + Timestamp: time.Now().Unix(), + SpaceType: "SpaceType", + ReplicationKey: replicationKey, + Seed: spaceHeaderSeed, + SpaceHeaderPayload: spaceHeaderPayload, + } + marhalled, err := header.Marshal() + require.NoError(t, err) + signature, err := accountKeys.SignKey.Sign(marhalled) + require.NoError(t, err) + rawHeader := &spacesyncproto.RawSpaceHeader{ + SpaceHeader: marhalled, + Signature: signature, + } + marhalledRawHeader, err := rawHeader.Marshal() + require.NoError(t, err) + id, err := cidutil.NewCidFromBytes(marhalled) + require.NoError(t, err) + spaceId := fmt.Sprintf("%s%s", id, strconv.FormatUint(replicationKey, 36)) + rawHeaderWithId := &spacesyncproto.RawSpaceHeaderWithId{ + RawHeader: marhalledRawHeader, + Id: spaceId, + } + err = validateCreateSpaceHeaderPayload(rawHeaderWithId) + assert.EqualErrorf(t, err, ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", objecttree.ErrIncorrectCid, err) +} + +func TestFailedHeaderPayloadForSpaceCreate_CidIsWrong(t *testing.T) { + accountKeys, err := accountdata.NewRandom() + require.NoError(t, err) + identity, err := accountKeys.SignKey.GetPublic().Marshall() + require.NoError(t, err) + spaceHeaderSeed := make([]byte, 32) + _, err = rand.Read(spaceHeaderSeed) + require.NoError(t, err) + spaceHeaderPayload := make([]byte, 32) + _, err = rand.Read(spaceHeaderPayload) + require.NoError(t, err) + replicationKey := rand2.Uint64() + header := &spacesyncproto.SpaceHeader{ + Identity: identity, + Timestamp: time.Now().Unix(), + SpaceType: "SpaceType", + ReplicationKey: replicationKey, + Seed: spaceHeaderSeed, + SpaceHeaderPayload: spaceHeaderPayload, + } + marhalled, err := header.Marshal() + require.NoError(t, err) + signature, err := accountKeys.SignKey.Sign(marhalled) + require.NoError(t, err) + rawHeader := &spacesyncproto.RawSpaceHeader{ + SpaceHeader: marhalled, + Signature: signature, + } + marhalledRawHeader, err := rawHeader.Marshal() + require.NoError(t, err) + id := "faisdfjpiocpoakopkop34" + spaceId := fmt.Sprintf("%s.%s", id, strconv.FormatUint(replicationKey, 36)) + rawHeaderWithId := &spacesyncproto.RawSpaceHeaderWithId{ + RawHeader: marhalledRawHeader, + Id: spaceId, + } + err = validateCreateSpaceHeaderPayload(rawHeaderWithId) + assert.EqualErrorf(t, err, objecttree.ErrIncorrectCid.Error(), "Error should be: %v, got: %v", objecttree.ErrIncorrectCid, err) +} + +func TestFailedHeaderPayloadForSpaceCreate_SignedWithAnotherIdentity(t *testing.T) { + accountKeys, err := accountdata.NewRandom() + require.NoError(t, err) + identity, err := accountKeys.SignKey.GetPublic().Marshall() + require.NoError(t, err) + spaceHeaderSeed := make([]byte, 32) + _, err = rand.Read(spaceHeaderSeed) + require.NoError(t, err) + spaceHeaderPayload := make([]byte, 32) + _, err = rand.Read(spaceHeaderPayload) + require.NoError(t, err) + replicationKey := rand2.Uint64() + header := &spacesyncproto.SpaceHeader{ + Identity: identity, + Timestamp: time.Now().Unix(), + SpaceType: "SpaceType", + ReplicationKey: replicationKey, + Seed: spaceHeaderSeed, + SpaceHeaderPayload: spaceHeaderPayload, + } + marhalled, err := header.Marshal() + require.NoError(t, err) + anotherAccountKeys, err := accountdata.NewRandom() + signature, err := anotherAccountKeys.SignKey.Sign(marhalled) + require.NoError(t, err) + rawHeader := &spacesyncproto.RawSpaceHeader{ + SpaceHeader: marhalled, + Signature: signature, + } + marhalledRawHeader, err := rawHeader.Marshal() + require.NoError(t, err) + id := "faisdfjpiocpoakopkop34" + spaceId := fmt.Sprintf("%s.%s", id, strconv.FormatUint(replicationKey, 36)) + rawHeaderWithId := &spacesyncproto.RawSpaceHeaderWithId{ + RawHeader: marhalledRawHeader, + Id: spaceId, + } + err = validateCreateSpaceHeaderPayload(rawHeaderWithId) + assert.EqualErrorf(t, err, objecttree.ErrIncorrectCid.Error(), "Error should be: %v, got: %v", objecttree.ErrIncorrectCid, err) +} + +func TestSuccessAclPayloadSpace(t *testing.T) { + accountKeys, err := accountdata.NewRandom() + require.NoError(t, err) + identity, err := accountKeys.SignKey.GetPublic().Marshall() + require.NoError(t, err) + readKeyBytes := make([]byte, 32) + _, err = rand.Read(readKeyBytes) + require.NoError(t, err) + readKey, err := accountKeys.SignKey.GetPublic().Encrypt(readKeyBytes) + require.NoError(t, err) + masterKey, _, err := crypto.GenerateRandomEd25519KeyPair() + require.NoError(t, err) + rawIdentity, err := accountKeys.SignKey.GetPublic().Raw() + require.NoError(t, err) + identitySignature, err := masterKey.Sign(rawIdentity) + require.NoError(t, err) + rawMasterKey, err := masterKey.Raw() + require.NoError(t, err) + aclRoot := aclrecordproto.AclRoot{ + Identity: identity, + MasterKey: rawMasterKey, + SpaceId: "SpaceId", + EncryptedReadKey: readKey, + Timestamp: time.Now().Unix(), + IdentitySignature: identitySignature, + } + marshalled, err := aclRoot.Marshal() + require.NoError(t, err) + signature, err := accountKeys.SignKey.Sign(marshalled) + rawAclRecord := &aclrecordproto.RawAclRecord{ + Payload: marshalled, + Signature: signature, + } + marshalledRaw, err := rawAclRecord.Marshal() + require.NoError(t, err) + aclHeadId, err := cidutil.NewCidFromBytes(marshalledRaw) + require.NoError(t, err) + rawWithId := &aclrecordproto.RawAclRecordWithId{ + Payload: marshalledRaw, + Id: aclHeadId, + } + err = validateCreateSpaceAclPayload(rawWithId) + require.NoError(t, err) +} + +func TestFailAclPayloadSpace_IncorrectCid(t *testing.T) { + accountKeys, err := accountdata.NewRandom() + require.NoError(t, err) + identity, err := accountKeys.SignKey.GetPublic().Marshall() + require.NoError(t, err) + readKeyBytes := make([]byte, 32) + _, err = rand.Read(readKeyBytes) + require.NoError(t, err) + readKey, err := accountKeys.SignKey.GetPublic().Encrypt(readKeyBytes) + require.NoError(t, err) + masterKey, _, err := crypto.GenerateRandomEd25519KeyPair() + require.NoError(t, err) + rawIdentity, err := accountKeys.SignKey.GetPublic().Raw() + require.NoError(t, err) + identitySignature, err := masterKey.Sign(rawIdentity) + require.NoError(t, err) + rawMasterKey, err := masterKey.Raw() + require.NoError(t, err) + aclRoot := aclrecordproto.AclRoot{ + Identity: identity, + MasterKey: rawMasterKey, + SpaceId: "SpaceId", + EncryptedReadKey: readKey, + Timestamp: time.Now().Unix(), + IdentitySignature: identitySignature, + } + marshalled, err := aclRoot.Marshal() + require.NoError(t, err) + signature, err := accountKeys.SignKey.Sign(marshalled) + rawAclRecord := &aclrecordproto.RawAclRecord{ + Payload: marshalled, + Signature: signature, + } + marshalledRaw, err := rawAclRecord.Marshal() + require.NoError(t, err) + aclHeadId := "rand" + rawWithId := &aclrecordproto.RawAclRecordWithId{ + Payload: marshalledRaw, + Id: aclHeadId, + } + err = validateCreateSpaceAclPayload(rawWithId) + assert.EqualErrorf(t, err, objecttree.ErrIncorrectCid.Error(), "Error should be: %v, got: %v", objecttree.ErrIncorrectCid, err) +} + +func TestFailedAclPayloadSpace_IncorrectSignature(t *testing.T) { + accountKeys, err := accountdata.NewRandom() + require.NoError(t, err) + identity, err := accountKeys.SignKey.GetPublic().Marshall() + require.NoError(t, err) + readKeyBytes := make([]byte, 32) + _, err = rand.Read(readKeyBytes) + require.NoError(t, err) + readKey, err := accountKeys.SignKey.GetPublic().Encrypt(readKeyBytes) + require.NoError(t, err) + masterKey, _, err := crypto.GenerateRandomEd25519KeyPair() + require.NoError(t, err) + rawIdentity, err := accountKeys.SignKey.GetPublic().Raw() + require.NoError(t, err) + identitySignature, err := masterKey.Sign(rawIdentity) + require.NoError(t, err) + rawMasterKey, err := masterKey.Raw() + require.NoError(t, err) + aclRoot := aclrecordproto.AclRoot{ + Identity: identity, + MasterKey: rawMasterKey, + SpaceId: "SpaceId", + EncryptedReadKey: readKey, + Timestamp: time.Now().Unix(), + IdentitySignature: identitySignature, + } + marshalled, err := aclRoot.Marshal() + require.NoError(t, err) + rawAclRecord := &aclrecordproto.RawAclRecord{ + Payload: marshalled, + Signature: marshalled, + } + marshalledRaw, err := rawAclRecord.Marshal() + require.NoError(t, err) + aclHeadId, err := cidutil.NewCidFromBytes(marshalledRaw) + require.NoError(t, err) + rawWithId := &aclrecordproto.RawAclRecordWithId{ + Payload: marshalledRaw, + Id: aclHeadId, + } + err = validateCreateSpaceAclPayload(rawWithId) + assert.NotNil(t, err) + assert.EqualErrorf(t, err, ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", ErrIncorrectSpaceHeader, err) +} + +func TestFailedAclPayloadSpace_IncorrectIdentitySignature(t *testing.T) { + accountKeys, err := accountdata.NewRandom() + require.NoError(t, err) + identity, err := accountKeys.SignKey.GetPublic().Marshall() + require.NoError(t, err) + readKeyBytes := make([]byte, 32) + _, err = rand.Read(readKeyBytes) + require.NoError(t, err) + readKey, err := accountKeys.SignKey.GetPublic().Encrypt(readKeyBytes) + require.NoError(t, err) + masterKey, _, err := crypto.GenerateRandomEd25519KeyPair() + require.NoError(t, err) + rawMasterKey, err := masterKey.Raw() + require.NoError(t, err) + aclRoot := aclrecordproto.AclRoot{ + Identity: identity, + MasterKey: rawMasterKey, + SpaceId: "SpaceId", + EncryptedReadKey: readKey, + Timestamp: time.Now().Unix(), + IdentitySignature: identity, + } + marshalled, err := aclRoot.Marshal() + require.NoError(t, err) + signature, err := accountKeys.SignKey.Sign(marshalled) + rawAclRecord := &aclrecordproto.RawAclRecord{ + Payload: marshalled, + Signature: signature, + } + marshalledRaw, err := rawAclRecord.Marshal() + require.NoError(t, err) + aclHeadId, err := cidutil.NewCidFromBytes(marshalledRaw) + require.NoError(t, err) + rawWithId := &aclrecordproto.RawAclRecordWithId{ + Payload: marshalledRaw, + Id: aclHeadId, + } + err = validateCreateSpaceAclPayload(rawWithId) + assert.EqualErrorf(t, err, ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", ErrIncorrectSpaceHeader, err) +} + +func TestSuccessSettingsPayloadSpace(t *testing.T) { + accountKeys, err := accountdata.NewRandom() + require.NoError(t, err) + identity, err := accountKeys.SignKey.GetPublic().Marshall() + require.NoError(t, err) + spaceSettingsSeed := make([]byte, 32) + _, err = rand.Read(spaceSettingsSeed) + require.NoError(t, err) + changePayload := make([]byte, 32) + _, err = rand.Read(changePayload) + require.NoError(t, err) + rootChange := &treechangeproto.RootChange{ + AclHeadId: "AclHeadId", + SpaceId: "SpaceId", + ChangeType: "ChangeType", + Timestamp: time.Now().Unix(), + Seed: spaceSettingsSeed, + Identity: identity, + ChangePayload: changePayload, + } + marshalledChange, err := rootChange.Marshal() + require.NoError(t, err) + signature, err := accountKeys.SignKey.Sign(marshalledChange) + require.NoError(t, err) + raw := &treechangeproto.RawTreeChange{ + Payload: marshalledChange, + Signature: signature, + } + marshalledRawChange, err := raw.Marshal() + id, err := cidutil.NewCidFromBytes(marshalledRawChange) + require.NoError(t, err) + rawIdChange := &treechangeproto.RawTreeChangeWithId{ + RawChange: marshalledRawChange, + Id: id, + } + err = validateCreateSpaceSettingsPayload(rawIdChange) + require.NoError(t, err) +} + +func TestFailSettingsPayloadSpace_InvalidSignature(t *testing.T) { + accountKeys, err := accountdata.NewRandom() + require.NoError(t, err) + identity, err := accountKeys.SignKey.GetPublic().Marshall() + require.NoError(t, err) + spaceSettingsSeed := make([]byte, 32) + _, err = rand.Read(spaceSettingsSeed) + require.NoError(t, err) + changePayload := make([]byte, 32) + _, err = rand.Read(changePayload) + require.NoError(t, err) + rootChange := &treechangeproto.RootChange{ + AclHeadId: "AclHeadId", + SpaceId: "SpaceId", + ChangeType: "ChangeType", + Timestamp: time.Now().Unix(), + Seed: spaceSettingsSeed, + Identity: identity, + ChangePayload: changePayload, + } + marshalledChange, err := rootChange.Marshal() + require.NoError(t, err) + raw := &treechangeproto.RawTreeChange{ + Payload: marshalledChange, + Signature: marshalledChange, + } + marshalledRawChange, err := raw.Marshal() + id, err := cidutil.NewCidFromBytes(marshalledRawChange) + require.NoError(t, err) + rawIdChange := &treechangeproto.RawTreeChangeWithId{ + RawChange: marshalledRawChange, + Id: id, + } + err = validateCreateSpaceSettingsPayload(rawIdChange) + assert.EqualErrorf(t, err, ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", ErrIncorrectSpaceHeader, err) +} + +func TestFailSettingsPayloadSpace_InvalidCid(t *testing.T) { + accountKeys, err := accountdata.NewRandom() + require.NoError(t, err) + identity, err := accountKeys.SignKey.GetPublic().Marshall() + require.NoError(t, err) + spaceSettingsSeed := make([]byte, 32) + _, err = rand.Read(spaceSettingsSeed) + require.NoError(t, err) + changePayload := make([]byte, 32) + _, err = rand.Read(changePayload) + require.NoError(t, err) + rootChange := &treechangeproto.RootChange{ + AclHeadId: "AclHeadId", + SpaceId: "SpaceId", + ChangeType: "ChangeType", + Timestamp: time.Now().Unix(), + Seed: spaceSettingsSeed, + Identity: identity, + ChangePayload: changePayload, + } + marshalledChange, err := rootChange.Marshal() + require.NoError(t, err) + signature, err := accountKeys.SignKey.Sign(marshalledChange) + require.NoError(t, err) + raw := &treechangeproto.RawTreeChange{ + Payload: marshalledChange, + Signature: signature, + } + marshalledRawChange, err := raw.Marshal() + id := "id" + require.NoError(t, err) + rawIdChange := &treechangeproto.RawTreeChangeWithId{ + RawChange: marshalledRawChange, + Id: id, + } + err = validateCreateSpaceSettingsPayload(rawIdChange) + assert.EqualErrorf(t, err, ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", ErrIncorrectSpaceHeader, err) +} From 022893dbc942b84f2c153380ebddaafc1a000021 Mon Sep 17 00:00:00 2001 From: Dmitry Bilienko Date: Thu, 13 Apr 2023 15:19:58 +0500 Subject: [PATCH 2/4] Additional validation of identifiers and new unit tests. --- commonspace/spacestorage/spacestorage.go | 54 ++- commonspace/spacestorage/spacestorage_test.go | 329 +++++++++++++----- 2 files changed, 288 insertions(+), 95 deletions(-) diff --git a/commonspace/spacestorage/spacestorage.go b/commonspace/spacestorage/spacestorage.go index af4ab7e5..82961cba 100644 --- a/commonspace/spacestorage/spacestorage.go +++ b/commonspace/spacestorage/spacestorage.go @@ -2,7 +2,6 @@ package spacestorage import ( - "bytes" "context" "errors" "fmt" @@ -73,16 +72,24 @@ func ValidateSpaceStorageCreatePayload(payload SpaceStorageCreatePayload) (err e if err != nil { return } - err = validateCreateSpaceAclPayload(payload.AclWithId) + aclSpaceId, err := validateCreateSpaceAclPayload(payload.AclWithId) if err != nil { return } - err = validateCreateSpaceSettingsPayload(payload.SpaceSettingsWithId) + aclHeadId, settingsSpaceId, err := validateCreateSpaceSettingsPayload(payload.SpaceSettingsWithId) if err != nil { return } + if aclSpaceId != payload.SpaceHeaderWithId.Id || aclSpaceId != settingsSpaceId { + err = ErrIncorrectSpaceHeader + return + } + if aclHeadId != payload.AclWithId.Id { + err = ErrIncorrectSpaceHeader + return + } - return nil + return } func validateCreateSpaceHeaderPayload(rawHeaderWithId *spacesyncproto.RawSpaceHeaderWithId) (err error) { @@ -96,7 +103,6 @@ func validateCreateSpaceHeaderPayload(rawHeaderWithId *spacesyncproto.RawSpaceHe if err != nil { return } - split := strings.Split(rawHeaderWithId.Id, ".") if len(split) != 2 { return ErrIncorrectSpaceHeader @@ -106,13 +112,18 @@ func validateCreateSpaceHeaderPayload(rawHeaderWithId *spacesyncproto.RawSpaceHe return } payloadIdentity, err := crypto.UnmarshalEd25519PublicKeyProto(header.Identity) + if err != nil { + return + } res, err := payloadIdentity.Verify(rawSpaceHeader.SpaceHeader, rawSpaceHeader.Signature) if err != nil || !res { err = ErrIncorrectSpaceHeader return } - id, err := cidutil.NewCidFromBytes(rawSpaceHeader.SpaceHeader) + if err != nil { + return + } requiredSpaceId := fmt.Sprintf("%s.%s", id, strconv.FormatUint(header.ReplicationKey, 36)) if requiredSpaceId != rawHeaderWithId.Id { err = ErrIncorrectSpaceHeader @@ -122,7 +133,7 @@ func validateCreateSpaceHeaderPayload(rawHeaderWithId *spacesyncproto.RawSpaceHe return } -func validateCreateSpaceAclPayload(rawWithId *aclrecordproto.RawAclRecordWithId) (err error) { +func validateCreateSpaceAclPayload(rawWithId *aclrecordproto.RawAclRecordWithId) (spaceId string, err error) { if !cidutil.VerifyCid(rawWithId.Payload, rawWithId.Id) { err = objecttree.ErrIncorrectCid return @@ -134,24 +145,33 @@ func validateCreateSpaceAclPayload(rawWithId *aclrecordproto.RawAclRecordWithId) } var aclRoot aclrecordproto.AclRoot err = proto.Unmarshal(rawAcl.Payload, &aclRoot) + if err != nil { + return + } payloadIdentity, err := crypto.UnmarshalEd25519PublicKeyProto(aclRoot.Identity) + if err != nil { + return + } res, err := payloadIdentity.Verify(rawAcl.Payload, rawAcl.Signature) if err != nil || !res { err = ErrIncorrectSpaceHeader return } - masterKey, err := crypto.UnmarshalEd25519PrivateKey(aclRoot.MasterKey) - identity, err := crypto.UnmarshalEd25519PublicKeyProto(aclRoot.Identity) - rawIdentity, err := identity.Raw() - signedIdentity, err := masterKey.Sign(rawIdentity) - if !bytes.Equal(signedIdentity, aclRoot.IdentitySignature) { + masterKey, err := crypto.UnmarshalEd25519PublicKeyProto(aclRoot.MasterKey) + if err != nil { + return + } + res, err = masterKey.Verify(aclRoot.Identity, aclRoot.IdentitySignature) + if err != nil || !res { err = ErrIncorrectSpaceHeader return } + spaceId = aclRoot.SpaceId + return } -func validateCreateSpaceSettingsPayload(rawWithId *treechangeproto.RawTreeChangeWithId) (err error) { +func validateCreateSpaceSettingsPayload(rawWithId *treechangeproto.RawTreeChangeWithId) (aclHeadId string, spaceId string, err error) { var raw treechangeproto.RawTreeChange err = proto.Unmarshal(rawWithId.RawChange, &raw) if err != nil { @@ -159,7 +179,13 @@ func validateCreateSpaceSettingsPayload(rawWithId *treechangeproto.RawTreeChange } var rootChange treechangeproto.RootChange err = proto.Unmarshal(raw.Payload, &rootChange) + if err != nil { + return + } payloadIdentity, err := crypto.UnmarshalEd25519PublicKeyProto(rootChange.Identity) + if err != nil { + return + } res, err := payloadIdentity.Verify(raw.Payload, raw.Signature) if err != nil || !res { err = ErrIncorrectSpaceHeader @@ -170,6 +196,8 @@ func validateCreateSpaceSettingsPayload(rawWithId *treechangeproto.RawTreeChange err = ErrIncorrectSpaceHeader return } + spaceId = rootChange.SpaceId + aclHeadId = rootChange.AclHeadId return } diff --git a/commonspace/spacestorage/spacestorage_test.go b/commonspace/spacestorage/spacestorage_test.go index 2eabb66f..d47935b0 100644 --- a/commonspace/spacestorage/spacestorage_test.go +++ b/commonspace/spacestorage/spacestorage_test.go @@ -21,40 +21,8 @@ import ( func TestSuccessHeaderPayloadForSpaceCreate(t *testing.T) { accountKeys, err := accountdata.NewRandom() require.NoError(t, err) - identity, err := accountKeys.SignKey.GetPublic().Marshall() + _, rawHeaderWithId, err := rawHeaderWithId(accountKeys) require.NoError(t, err) - spaceHeaderSeed := make([]byte, 32) - _, err = rand.Read(spaceHeaderSeed) - require.NoError(t, err) - spaceHeaderPayload := make([]byte, 32) - _, err = rand.Read(spaceHeaderPayload) - require.NoError(t, err) - replicationKey := rand2.Uint64() - header := &spacesyncproto.SpaceHeader{ - Identity: identity, - Timestamp: time.Now().Unix(), - SpaceType: "SpaceType", - ReplicationKey: replicationKey, - Seed: spaceHeaderSeed, - SpaceHeaderPayload: spaceHeaderPayload, - } - marhalled, err := header.Marshal() - require.NoError(t, err) - signature, err := accountKeys.SignKey.Sign(marhalled) - require.NoError(t, err) - rawHeader := &spacesyncproto.RawSpaceHeader{ - SpaceHeader: marhalled, - Signature: signature, - } - marhalledRawHeader, err := rawHeader.Marshal() - require.NoError(t, err) - id, err := cidutil.NewCidFromBytes(marhalled) - require.NoError(t, err) - spaceId := fmt.Sprintf("%s.%s", id, strconv.FormatUint(replicationKey, 36)) - rawHeaderWithId := &spacesyncproto.RawSpaceHeaderWithId{ - RawHeader: marhalledRawHeader, - Id: spaceId, - } err = validateCreateSpaceHeaderPayload(rawHeaderWithId) require.NoError(t, err) } @@ -183,46 +151,11 @@ func TestFailedHeaderPayloadForSpaceCreate_SignedWithAnotherIdentity(t *testing. func TestSuccessAclPayloadSpace(t *testing.T) { accountKeys, err := accountdata.NewRandom() + spaceId := "AnySpaceId" + _, rawWithId, err := rawAclWithId(accountKeys, spaceId) require.NoError(t, err) - identity, err := accountKeys.SignKey.GetPublic().Marshall() - require.NoError(t, err) - readKeyBytes := make([]byte, 32) - _, err = rand.Read(readKeyBytes) - require.NoError(t, err) - readKey, err := accountKeys.SignKey.GetPublic().Encrypt(readKeyBytes) - require.NoError(t, err) - masterKey, _, err := crypto.GenerateRandomEd25519KeyPair() - require.NoError(t, err) - rawIdentity, err := accountKeys.SignKey.GetPublic().Raw() - require.NoError(t, err) - identitySignature, err := masterKey.Sign(rawIdentity) - require.NoError(t, err) - rawMasterKey, err := masterKey.Raw() - require.NoError(t, err) - aclRoot := aclrecordproto.AclRoot{ - Identity: identity, - MasterKey: rawMasterKey, - SpaceId: "SpaceId", - EncryptedReadKey: readKey, - Timestamp: time.Now().Unix(), - IdentitySignature: identitySignature, - } - marshalled, err := aclRoot.Marshal() - require.NoError(t, err) - signature, err := accountKeys.SignKey.Sign(marshalled) - rawAclRecord := &aclrecordproto.RawAclRecord{ - Payload: marshalled, - Signature: signature, - } - marshalledRaw, err := rawAclRecord.Marshal() - require.NoError(t, err) - aclHeadId, err := cidutil.NewCidFromBytes(marshalledRaw) - require.NoError(t, err) - rawWithId := &aclrecordproto.RawAclRecordWithId{ - Payload: marshalledRaw, - Id: aclHeadId, - } - err = validateCreateSpaceAclPayload(rawWithId) + validationSpaceId, err := validateCreateSpaceAclPayload(rawWithId) + require.Equal(t, validationSpaceId, spaceId) require.NoError(t, err) } @@ -242,7 +175,7 @@ func TestFailAclPayloadSpace_IncorrectCid(t *testing.T) { require.NoError(t, err) identitySignature, err := masterKey.Sign(rawIdentity) require.NoError(t, err) - rawMasterKey, err := masterKey.Raw() + rawMasterKey, err := masterKey.GetPublic().Marshall() require.NoError(t, err) aclRoot := aclrecordproto.AclRoot{ Identity: identity, @@ -266,7 +199,7 @@ func TestFailAclPayloadSpace_IncorrectCid(t *testing.T) { Payload: marshalledRaw, Id: aclHeadId, } - err = validateCreateSpaceAclPayload(rawWithId) + _, err = validateCreateSpaceAclPayload(rawWithId) assert.EqualErrorf(t, err, objecttree.ErrIncorrectCid.Error(), "Error should be: %v, got: %v", objecttree.ErrIncorrectCid, err) } @@ -286,7 +219,7 @@ func TestFailedAclPayloadSpace_IncorrectSignature(t *testing.T) { require.NoError(t, err) identitySignature, err := masterKey.Sign(rawIdentity) require.NoError(t, err) - rawMasterKey, err := masterKey.Raw() + rawMasterKey, err := masterKey.GetPublic().Raw() require.NoError(t, err) aclRoot := aclrecordproto.AclRoot{ Identity: identity, @@ -310,7 +243,7 @@ func TestFailedAclPayloadSpace_IncorrectSignature(t *testing.T) { Payload: marshalledRaw, Id: aclHeadId, } - err = validateCreateSpaceAclPayload(rawWithId) + _, err = validateCreateSpaceAclPayload(rawWithId) assert.NotNil(t, err) assert.EqualErrorf(t, err, ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", ErrIncorrectSpaceHeader, err) } @@ -327,7 +260,7 @@ func TestFailedAclPayloadSpace_IncorrectIdentitySignature(t *testing.T) { require.NoError(t, err) masterKey, _, err := crypto.GenerateRandomEd25519KeyPair() require.NoError(t, err) - rawMasterKey, err := masterKey.Raw() + rawMasterKey, err := masterKey.GetPublic().Marshall() require.NoError(t, err) aclRoot := aclrecordproto.AclRoot{ Identity: identity, @@ -352,7 +285,7 @@ func TestFailedAclPayloadSpace_IncorrectIdentitySignature(t *testing.T) { Payload: marshalledRaw, Id: aclHeadId, } - err = validateCreateSpaceAclPayload(rawWithId) + _, err = validateCreateSpaceAclPayload(rawWithId) assert.EqualErrorf(t, err, ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", ErrIncorrectSpaceHeader, err) } @@ -367,9 +300,10 @@ func TestSuccessSettingsPayloadSpace(t *testing.T) { changePayload := make([]byte, 32) _, err = rand.Read(changePayload) require.NoError(t, err) + spaceId := "SpaceId" rootChange := &treechangeproto.RootChange{ AclHeadId: "AclHeadId", - SpaceId: "SpaceId", + SpaceId: spaceId, ChangeType: "ChangeType", Timestamp: time.Now().Unix(), Seed: spaceSettingsSeed, @@ -391,7 +325,8 @@ func TestSuccessSettingsPayloadSpace(t *testing.T) { RawChange: marshalledRawChange, Id: id, } - err = validateCreateSpaceSettingsPayload(rawIdChange) + _, validationSpaceId, err := validateCreateSpaceSettingsPayload(rawIdChange) + require.Equal(t, validationSpaceId, spaceId) require.NoError(t, err) } @@ -428,7 +363,7 @@ func TestFailSettingsPayloadSpace_InvalidSignature(t *testing.T) { RawChange: marshalledRawChange, Id: id, } - err = validateCreateSpaceSettingsPayload(rawIdChange) + _, _, err = validateCreateSpaceSettingsPayload(rawIdChange) assert.EqualErrorf(t, err, ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", ErrIncorrectSpaceHeader, err) } @@ -467,6 +402,236 @@ func TestFailSettingsPayloadSpace_InvalidCid(t *testing.T) { RawChange: marshalledRawChange, Id: id, } - err = validateCreateSpaceSettingsPayload(rawIdChange) + _, _, err = validateCreateSpaceSettingsPayload(rawIdChange) assert.EqualErrorf(t, err, ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", ErrIncorrectSpaceHeader, err) } + +func TestSuccessSameIds(t *testing.T) { + accountKeys, err := accountdata.NewRandom() + require.NoError(t, err) + spaceId, rawHeaderWithId, err := rawHeaderWithId(accountKeys) + require.NoError(t, err) + aclHeadId, rawAclWithId, err := rawAclWithId(accountKeys, spaceId) + require.NoError(t, err) + rawSettingsPayload, err := rawSettingsPayload(accountKeys, spaceId, aclHeadId) + spacePayload := SpaceStorageCreatePayload{ + AclWithId: rawAclWithId, + SpaceHeaderWithId: rawHeaderWithId, + SpaceSettingsWithId: rawSettingsPayload, + } + err = ValidateSpaceStorageCreatePayload(spacePayload) + require.NoError(t, err) +} + +func TestFailWithAclWrongSpaceId(t *testing.T) { + accountKeys, err := accountdata.NewRandom() + require.NoError(t, err) + spaceId, rawHeaderWithId, err := rawHeaderWithId(accountKeys) + require.NoError(t, err) + aclHeadId, rawAclWithId, err := rawAclWithId(accountKeys, "spaceId") + require.NoError(t, err) + rawSettingsPayload, err := rawSettingsPayload(accountKeys, spaceId, aclHeadId) + spacePayload := SpaceStorageCreatePayload{ + AclWithId: rawAclWithId, + SpaceHeaderWithId: rawHeaderWithId, + SpaceSettingsWithId: rawSettingsPayload, + } + err = ValidateSpaceStorageCreatePayload(spacePayload) + assert.EqualErrorf(t, err, ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", ErrIncorrectSpaceHeader, err) +} + +func TestFailWithSettingsWrongSpaceId(t *testing.T) { + accountKeys, err := accountdata.NewRandom() + require.NoError(t, err) + spaceId, rawHeaderWithId, err := rawHeaderWithId(accountKeys) + require.NoError(t, err) + aclHeadId, rawAclWithId, err := rawAclWithId(accountKeys, spaceId) + require.NoError(t, err) + rawSettingsPayload, err := rawSettingsPayload(accountKeys, "spaceId", aclHeadId) + spacePayload := SpaceStorageCreatePayload{ + AclWithId: rawAclWithId, + SpaceHeaderWithId: rawHeaderWithId, + SpaceSettingsWithId: rawSettingsPayload, + } + err = ValidateSpaceStorageCreatePayload(spacePayload) + assert.EqualErrorf(t, err, ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", ErrIncorrectSpaceHeader, err) +} + +func TestFailWithWrongAclHeadIdInSettingsPayload(t *testing.T) { + accountKeys, err := accountdata.NewRandom() + require.NoError(t, err) + spaceId, rawHeaderWithId, err := rawHeaderWithId(accountKeys) + require.NoError(t, err) + _, rawAclWithId, err := rawAclWithId(accountKeys, spaceId) + require.NoError(t, err) + rawSettingsPayload, err := rawSettingsPayload(accountKeys, spaceId, "aclHeadId") + spacePayload := SpaceStorageCreatePayload{ + AclWithId: rawAclWithId, + SpaceHeaderWithId: rawHeaderWithId, + SpaceSettingsWithId: rawSettingsPayload, + } + err = ValidateSpaceStorageCreatePayload(spacePayload) + assert.EqualErrorf(t, err, ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", ErrIncorrectSpaceHeader, err) +} + +func rawSettingsPayload(accountKeys *accountdata.AccountKeys, spaceId, aclHeadId string) (rawIdChange *treechangeproto.RawTreeChangeWithId, err error) { + identity, err := accountKeys.SignKey.GetPublic().Marshall() + if err != nil { + return + } + spaceSettingsSeed := make([]byte, 32) + _, err = rand.Read(spaceSettingsSeed) + if err != nil { + return + } + changePayload := make([]byte, 32) + _, err = rand.Read(changePayload) + if err != nil { + return + } + rootChange := &treechangeproto.RootChange{ + AclHeadId: aclHeadId, + SpaceId: spaceId, + ChangeType: "ChangeType", + Timestamp: time.Now().Unix(), + Seed: spaceSettingsSeed, + Identity: identity, + ChangePayload: changePayload, + } + marshalledChange, err := rootChange.Marshal() + if err != nil { + return + } + signature, err := accountKeys.SignKey.Sign(marshalledChange) + if err != nil { + return + } + raw := &treechangeproto.RawTreeChange{ + Payload: marshalledChange, + Signature: signature, + } + marshalledRawChange, err := raw.Marshal() + id, err := cidutil.NewCidFromBytes(marshalledRawChange) + if err != nil { + return + } + rawIdChange = &treechangeproto.RawTreeChangeWithId{ + RawChange: marshalledRawChange, + Id: id, + } + + return +} + +func rawAclWithId(accountKeys *accountdata.AccountKeys, spaceId string) (aclHeadId string, rawWithId *aclrecordproto.RawAclRecordWithId, err error) { + readKeyBytes := make([]byte, 32) + _, err = rand.Read(readKeyBytes) + if err != nil { + return + } + readKey, err := accountKeys.SignKey.GetPublic().Encrypt(readKeyBytes) + if err != nil { + return + } + masterKey, _, err := crypto.GenerateRandomEd25519KeyPair() + if err != nil { + return + } + masterPubKey := masterKey.GetPublic() + identity, err := accountKeys.SignKey.GetPublic().Marshall() + if err != nil { + return + } + identitySignature, err := masterKey.Sign(identity) + if err != nil { + return + } + rawMasterKey, err := masterPubKey.Marshall() + if err != nil { + return + } + aclRoot := aclrecordproto.AclRoot{ + Identity: identity, + MasterKey: rawMasterKey, + SpaceId: spaceId, + EncryptedReadKey: readKey, + Timestamp: time.Now().Unix(), + IdentitySignature: identitySignature, + } + marshalled, err := aclRoot.Marshal() + if err != nil { + return + } + signature, err := accountKeys.SignKey.Sign(marshalled) + rawAclRecord := &aclrecordproto.RawAclRecord{ + Payload: marshalled, + Signature: signature, + } + marshalledRaw, err := rawAclRecord.Marshal() + if err != nil { + return + } + aclHeadId, err = cidutil.NewCidFromBytes(marshalledRaw) + if err != nil { + return + } + rawWithId = &aclrecordproto.RawAclRecordWithId{ + Payload: marshalledRaw, + Id: aclHeadId, + } + + return +} + +func rawHeaderWithId(accountKeys *accountdata.AccountKeys) (spaceId string, rawWithId *spacesyncproto.RawSpaceHeaderWithId, err error) { + identity, err := accountKeys.SignKey.GetPublic().Marshall() + if err != nil { + return + } + spaceHeaderSeed := make([]byte, 32) + _, err = rand.Read(spaceHeaderSeed) + if err != nil { + return + } + spaceHeaderPayload := make([]byte, 32) + _, err = rand.Read(spaceHeaderPayload) + if err != nil { + return + } + replicationKey := rand2.Uint64() + header := &spacesyncproto.SpaceHeader{ + Identity: identity, + Timestamp: time.Now().Unix(), + SpaceType: "SpaceType", + ReplicationKey: replicationKey, + Seed: spaceHeaderSeed, + SpaceHeaderPayload: spaceHeaderPayload, + } + marhalled, err := header.Marshal() + if err != nil { + return + } + signature, err := accountKeys.SignKey.Sign(marhalled) + if err != nil { + return + } + rawHeader := &spacesyncproto.RawSpaceHeader{ + SpaceHeader: marhalled, + Signature: signature, + } + marhalledRawHeader, err := rawHeader.Marshal() + if err != nil { + return + } + id, err := cidutil.NewCidFromBytes(marhalled) + if err != nil { + return + } + spaceId = fmt.Sprintf("%s.%s", id, strconv.FormatUint(replicationKey, 36)) + rawWithId = &spacesyncproto.RawSpaceHeaderWithId{ + RawHeader: marhalledRawHeader, + Id: spaceId, + } + + return +} From 5426e968d9705cd3a5686791e91ca2bfa5545b7d Mon Sep 17 00:00:00 2001 From: Dmitry Bilienko Date: Mon, 17 Apr 2023 17:15:48 +0500 Subject: [PATCH 3/4] Validation issues fix --- commonspace/spacestorage/spacestorage.go | 7 ++- commonspace/spacestorage/spacestorage_test.go | 58 ++++++++++++------- 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/commonspace/spacestorage/spacestorage.go b/commonspace/spacestorage/spacestorage.go index 82961cba..822e9a48 100644 --- a/commonspace/spacestorage/spacestorage.go +++ b/commonspace/spacestorage/spacestorage.go @@ -107,7 +107,7 @@ func validateCreateSpaceHeaderPayload(rawHeaderWithId *spacesyncproto.RawSpaceHe if len(split) != 2 { return ErrIncorrectSpaceHeader } - if !cidutil.VerifyCid(rawSpaceHeader.SpaceHeader, split[0]) { + if !cidutil.VerifyCid(rawHeaderWithId.RawHeader, split[0]) { err = objecttree.ErrIncorrectCid return } @@ -120,7 +120,7 @@ func validateCreateSpaceHeaderPayload(rawHeaderWithId *spacesyncproto.RawSpaceHe err = ErrIncorrectSpaceHeader return } - id, err := cidutil.NewCidFromBytes(rawSpaceHeader.SpaceHeader) + id, err := cidutil.NewCidFromBytes(rawHeaderWithId.RawHeader) if err != nil { return } @@ -148,7 +148,7 @@ func validateCreateSpaceAclPayload(rawWithId *aclrecordproto.RawAclRecordWithId) if err != nil { return } - payloadIdentity, err := crypto.UnmarshalEd25519PublicKeyProto(aclRoot.Identity) + payloadIdentity, err := crypto.UnmarshalEd25519PublicKey(aclRoot.Identity) if err != nil { return } @@ -161,6 +161,7 @@ func validateCreateSpaceAclPayload(rawWithId *aclrecordproto.RawAclRecordWithId) if err != nil { return } + res, err = masterKey.Verify(aclRoot.Identity, aclRoot.IdentitySignature) if err != nil || !res { err = ErrIncorrectSpaceHeader diff --git a/commonspace/spacestorage/spacestorage_test.go b/commonspace/spacestorage/spacestorage_test.go index d47935b0..1b4f9da6 100644 --- a/commonspace/spacestorage/spacestorage_test.go +++ b/commonspace/spacestorage/spacestorage_test.go @@ -65,7 +65,7 @@ func TestFailedHeaderPayloadForSpaceCreate_InvalidFormatSpaceId(t *testing.T) { Id: spaceId, } err = validateCreateSpaceHeaderPayload(rawHeaderWithId) - assert.EqualErrorf(t, err, ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", objecttree.ErrIncorrectCid, err) + assert.EqualErrorf(t, err, ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", ErrIncorrectSpaceHeader, err) } func TestFailedHeaderPayloadForSpaceCreate_CidIsWrong(t *testing.T) { @@ -206,8 +206,6 @@ func TestFailAclPayloadSpace_IncorrectCid(t *testing.T) { func TestFailedAclPayloadSpace_IncorrectSignature(t *testing.T) { accountKeys, err := accountdata.NewRandom() require.NoError(t, err) - identity, err := accountKeys.SignKey.GetPublic().Marshall() - require.NoError(t, err) readKeyBytes := make([]byte, 32) _, err = rand.Read(readKeyBytes) require.NoError(t, err) @@ -222,7 +220,7 @@ func TestFailedAclPayloadSpace_IncorrectSignature(t *testing.T) { rawMasterKey, err := masterKey.GetPublic().Raw() require.NoError(t, err) aclRoot := aclrecordproto.AclRoot{ - Identity: identity, + Identity: rawIdentity, MasterKey: rawMasterKey, SpaceId: "SpaceId", EncryptedReadKey: readKey, @@ -249,38 +247,56 @@ func TestFailedAclPayloadSpace_IncorrectSignature(t *testing.T) { } func TestFailedAclPayloadSpace_IncorrectIdentitySignature(t *testing.T) { + spaceId := "AnySpaceId" accountKeys, err := accountdata.NewRandom() require.NoError(t, err) - identity, err := accountKeys.SignKey.GetPublic().Marshall() - require.NoError(t, err) readKeyBytes := make([]byte, 32) _, err = rand.Read(readKeyBytes) - require.NoError(t, err) + if err != nil { + return + } readKey, err := accountKeys.SignKey.GetPublic().Encrypt(readKeyBytes) - require.NoError(t, err) + if err != nil { + return + } masterKey, _, err := crypto.GenerateRandomEd25519KeyPair() - require.NoError(t, err) - rawMasterKey, err := masterKey.GetPublic().Marshall() - require.NoError(t, err) + if err != nil { + return + } + masterPubKey := masterKey.GetPublic() + rawIdentity, err := accountKeys.SignKey.GetPublic().Raw() + if err != nil { + return + } + rawMasterKey, err := masterPubKey.Marshall() + if err != nil { + return + } aclRoot := aclrecordproto.AclRoot{ - Identity: identity, + Identity: rawIdentity, MasterKey: rawMasterKey, - SpaceId: "SpaceId", + SpaceId: spaceId, EncryptedReadKey: readKey, Timestamp: time.Now().Unix(), - IdentitySignature: identity, + IdentitySignature: rawIdentity, } marshalled, err := aclRoot.Marshal() - require.NoError(t, err) + if err != nil { + return + } signature, err := accountKeys.SignKey.Sign(marshalled) rawAclRecord := &aclrecordproto.RawAclRecord{ Payload: marshalled, Signature: signature, } marshalledRaw, err := rawAclRecord.Marshal() - require.NoError(t, err) + if err != nil { + return + } aclHeadId, err := cidutil.NewCidFromBytes(marshalledRaw) - require.NoError(t, err) + if err != nil { + return + } rawWithId := &aclrecordproto.RawAclRecordWithId{ Payload: marshalledRaw, Id: aclHeadId, @@ -538,11 +554,11 @@ func rawAclWithId(accountKeys *accountdata.AccountKeys, spaceId string) (aclHead return } masterPubKey := masterKey.GetPublic() - identity, err := accountKeys.SignKey.GetPublic().Marshall() + rawIdentity, err := accountKeys.SignKey.GetPublic().Raw() if err != nil { return } - identitySignature, err := masterKey.Sign(identity) + identitySignature, err := masterKey.Sign(rawIdentity) if err != nil { return } @@ -551,7 +567,7 @@ func rawAclWithId(accountKeys *accountdata.AccountKeys, spaceId string) (aclHead return } aclRoot := aclrecordproto.AclRoot{ - Identity: identity, + Identity: rawIdentity, MasterKey: rawMasterKey, SpaceId: spaceId, EncryptedReadKey: readKey, @@ -623,7 +639,7 @@ func rawHeaderWithId(accountKeys *accountdata.AccountKeys) (spaceId string, rawW if err != nil { return } - id, err := cidutil.NewCidFromBytes(marhalled) + id, err := cidutil.NewCidFromBytes(marhalledRawHeader) if err != nil { return } From d2805a077dffa44a9462ae1b904845b3b6626641 Mon Sep 17 00:00:00 2001 From: Dmitry Bilienko Date: Tue, 18 Apr 2023 11:37:46 +0500 Subject: [PATCH 4/4] ACL Payload validation fix --- commonspace/spacestorage/spacestorage.go | 10 ++++++---- commonspace/spacestorage/spacestorage_test.go | 12 +++++++----- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/commonspace/spacestorage/spacestorage.go b/commonspace/spacestorage/spacestorage.go index 822e9a48..ebd4b68d 100644 --- a/commonspace/spacestorage/spacestorage.go +++ b/commonspace/spacestorage/spacestorage.go @@ -88,7 +88,6 @@ func ValidateSpaceStorageCreatePayload(payload SpaceStorageCreatePayload) (err e err = ErrIncorrectSpaceHeader return } - return } @@ -148,7 +147,7 @@ func validateCreateSpaceAclPayload(rawWithId *aclrecordproto.RawAclRecordWithId) if err != nil { return } - payloadIdentity, err := crypto.UnmarshalEd25519PublicKey(aclRoot.Identity) + payloadIdentity, err := crypto.UnmarshalEd25519PublicKeyProto(aclRoot.Identity) if err != nil { return } @@ -161,8 +160,11 @@ func validateCreateSpaceAclPayload(rawWithId *aclrecordproto.RawAclRecordWithId) if err != nil { return } - - res, err = masterKey.Verify(aclRoot.Identity, aclRoot.IdentitySignature) + rawIdentity, err := payloadIdentity.Raw() + if err != nil { + return + } + res, err = masterKey.Verify(rawIdentity, aclRoot.IdentitySignature) if err != nil || !res { err = ErrIncorrectSpaceHeader return diff --git a/commonspace/spacestorage/spacestorage_test.go b/commonspace/spacestorage/spacestorage_test.go index 1b4f9da6..8243291e 100644 --- a/commonspace/spacestorage/spacestorage_test.go +++ b/commonspace/spacestorage/spacestorage_test.go @@ -215,12 +215,13 @@ func TestFailedAclPayloadSpace_IncorrectSignature(t *testing.T) { require.NoError(t, err) rawIdentity, err := accountKeys.SignKey.GetPublic().Raw() require.NoError(t, err) + identity, err := accountKeys.SignKey.GetPublic().Marshall() identitySignature, err := masterKey.Sign(rawIdentity) require.NoError(t, err) rawMasterKey, err := masterKey.GetPublic().Raw() require.NoError(t, err) aclRoot := aclrecordproto.AclRoot{ - Identity: rawIdentity, + Identity: identity, MasterKey: rawMasterKey, SpaceId: "SpaceId", EncryptedReadKey: readKey, @@ -264,7 +265,7 @@ func TestFailedAclPayloadSpace_IncorrectIdentitySignature(t *testing.T) { return } masterPubKey := masterKey.GetPublic() - rawIdentity, err := accountKeys.SignKey.GetPublic().Raw() + identity, err := accountKeys.SignKey.GetPublic().Marshall() if err != nil { return } @@ -273,12 +274,12 @@ func TestFailedAclPayloadSpace_IncorrectIdentitySignature(t *testing.T) { return } aclRoot := aclrecordproto.AclRoot{ - Identity: rawIdentity, + Identity: identity, MasterKey: rawMasterKey, SpaceId: spaceId, EncryptedReadKey: readKey, Timestamp: time.Now().Unix(), - IdentitySignature: rawIdentity, + IdentitySignature: identity, } marshalled, err := aclRoot.Marshal() if err != nil { @@ -550,6 +551,7 @@ func rawAclWithId(accountKeys *accountdata.AccountKeys, spaceId string) (aclHead return } masterKey, _, err := crypto.GenerateRandomEd25519KeyPair() + identity, err := accountKeys.SignKey.GetPublic().Marshall() if err != nil { return } @@ -567,7 +569,7 @@ func rawAclWithId(accountKeys *accountdata.AccountKeys, spaceId string) (aclHead return } aclRoot := aclrecordproto.AclRoot{ - Identity: rawIdentity, + Identity: identity, MasterKey: rawMasterKey, SpaceId: spaceId, EncryptedReadKey: readKey,