Move validation to any-sync

This commit is contained in:
mcrakhman 2023-04-21 20:12:47 +02:00 committed by Mikhail Iudin
parent 7f9afe9ad3
commit 0281f006e6
No known key found for this signature in database
GPG Key ID: FAAAA8BAABDFF1C0
5 changed files with 847 additions and 838 deletions

View File

@ -1,14 +1,20 @@
package commonspace
import (
"fmt"
"github.com/anytypeio/any-sync/commonspace/object/acl/aclrecordproto"
"github.com/anytypeio/any-sync/commonspace/object/acl/list"
"github.com/anytypeio/any-sync/commonspace/object/tree/objecttree"
"github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto"
"github.com/anytypeio/any-sync/commonspace/spacestorage"
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
"github.com/anytypeio/any-sync/util/cidutil"
"github.com/anytypeio/any-sync/util/crypto"
"github.com/gogo/protobuf/proto"
"hash/fnv"
"math/rand"
"strconv"
"strings"
"time"
)
@ -180,3 +186,177 @@ func storagePayloadForSpaceDerive(payload SpaceDerivePayload) (storagePayload sp
}
return
}
func validateSpaceStorageCreatePayload(payload spacestorage.SpaceStorageCreatePayload) (err error) {
err = validateCreateSpaceHeaderPayload(payload.SpaceHeaderWithId)
if err != nil {
return
}
aclSpaceId, err := validateCreateSpaceAclPayload(payload.AclWithId)
if err != nil {
return
}
aclHeadId, settingsSpaceId, err := validateCreateSpaceSettingsPayload(payload.SpaceSettingsWithId)
if err != nil {
return
}
if aclSpaceId != payload.SpaceHeaderWithId.Id || aclSpaceId != settingsSpaceId {
err = spacestorage.ErrIncorrectSpaceHeader
return
}
if aclHeadId != payload.AclWithId.Id {
err = spacestorage.ErrIncorrectSpaceHeader
return
}
return
}
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 spacestorage.ErrIncorrectSpaceHeader
}
if !cidutil.VerifyCid(rawHeaderWithId.RawHeader, split[0]) {
err = objecttree.ErrIncorrectCid
return
}
payloadIdentity, err := crypto.UnmarshalEd25519PublicKeyProto(header.Identity)
if err != nil {
return
}
res, err := payloadIdentity.Verify(rawSpaceHeader.SpaceHeader, rawSpaceHeader.Signature)
if err != nil || !res {
err = spacestorage.ErrIncorrectSpaceHeader
return
}
id, err := cidutil.NewCidFromBytes(rawHeaderWithId.RawHeader)
if err != nil {
return
}
requiredSpaceId := fmt.Sprintf("%s.%s", id, strconv.FormatUint(header.ReplicationKey, 36))
if requiredSpaceId != rawHeaderWithId.Id {
err = spacestorage.ErrIncorrectSpaceHeader
return
}
return
}
func validateCreateSpaceAclPayload(rawWithId *aclrecordproto.RawAclRecordWithId) (spaceId string, 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)
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 = spacestorage.ErrIncorrectSpaceHeader
return
}
masterKey, err := crypto.UnmarshalEd25519PublicKeyProto(aclRoot.MasterKey)
if err != nil {
return
}
rawIdentity, err := payloadIdentity.Raw()
if err != nil {
return
}
res, err = masterKey.Verify(rawIdentity, aclRoot.IdentitySignature)
if err != nil || !res {
err = spacestorage.ErrIncorrectSpaceHeader
return
}
spaceId = aclRoot.SpaceId
return
}
func validateCreateSpaceSettingsPayload(rawWithId *treechangeproto.RawTreeChangeWithId) (aclHeadId string, spaceId string, 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)
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 = spacestorage.ErrIncorrectSpaceHeader
return
}
id, err := cidutil.NewCidFromBytes(rawWithId.RawChange)
if id != rawWithId.Id {
err = spacestorage.ErrIncorrectSpaceHeader
return
}
spaceId = rootChange.SpaceId
aclHeadId = rootChange.AclHeadId
return
}
// ValidateSpaceHeader Used in coordinator
func ValidateSpaceHeader(spaceId string, header []byte, identity crypto.PubKey) (err error) {
split := strings.Split(spaceId, ".")
if len(split) != 2 {
return spacestorage.ErrIncorrectSpaceHeader
}
if !cidutil.VerifyCid(header, split[0]) {
err = objecttree.ErrIncorrectCid
return
}
raw := &spacesyncproto.RawSpaceHeader{}
err = proto.Unmarshal(header, raw)
if err != nil {
return
}
payload := &spacesyncproto.SpaceHeader{}
err = proto.Unmarshal(raw.SpaceHeader, payload)
if err != nil {
return
}
payloadIdentity, err := crypto.UnmarshalEd25519PublicKeyProto(payload.Identity)
if err != nil {
return
}
if identity != nil && !payloadIdentity.Equals(identity) {
err = spacestorage.ErrIncorrectSpaceHeader
return
}
res, err := identity.Verify(raw.SpaceHeader, raw.Signature)
if err != nil || !res {
err = spacestorage.ErrIncorrectSpaceHeader
return
}
return
}

View File

@ -0,0 +1,655 @@
package commonspace
import (
"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/spacestorage"
"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"
"math/rand"
"strconv"
"testing"
"time"
)
func TestSuccessHeaderPayloadForSpaceCreate(t *testing.T) {
accountKeys, err := accountdata.NewRandom()
require.NoError(t, err)
_, rawHeaderWithId, err := rawHeaderWithId(accountKeys)
require.NoError(t, err)
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 := rand.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, spacestorage.ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", spacestorage.ErrIncorrectSpaceHeader, 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 := rand.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 := rand.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()
spaceId := "AnySpaceId"
_, rawWithId, err := rawAclWithId(accountKeys, spaceId)
require.NoError(t, err)
validationSpaceId, err := validateCreateSpaceAclPayload(rawWithId)
require.Equal(t, validationSpaceId, spaceId)
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.GetPublic().Marshall()
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)
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)
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: 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, spacestorage.ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", spacestorage.ErrIncorrectSpaceHeader, err)
}
func TestFailedAclPayloadSpace_IncorrectIdentitySignature(t *testing.T) {
spaceId := "AnySpaceId"
accountKeys, err := accountdata.NewRandom()
require.NoError(t, err)
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
}
rawMasterKey, err := masterPubKey.Marshall()
if err != nil {
return
}
aclRoot := aclrecordproto.AclRoot{
Identity: identity,
MasterKey: rawMasterKey,
SpaceId: spaceId,
EncryptedReadKey: readKey,
Timestamp: time.Now().Unix(),
IdentitySignature: identity,
}
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,
}
_, err = validateCreateSpaceAclPayload(rawWithId)
assert.EqualErrorf(t, err, spacestorage.ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", spacestorage.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)
spaceId := "SpaceId"
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,
}
_, validationSpaceId, err := validateCreateSpaceSettingsPayload(rawIdChange)
require.Equal(t, validationSpaceId, spaceId)
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, spacestorage.ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", spacestorage.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, spacestorage.ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", spacestorage.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 := spacestorage.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 := spacestorage.SpaceStorageCreatePayload{
AclWithId: rawAclWithId,
SpaceHeaderWithId: rawHeaderWithId,
SpaceSettingsWithId: rawSettingsPayload,
}
err = validateSpaceStorageCreatePayload(spacePayload)
assert.EqualErrorf(t, err, spacestorage.ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", spacestorage.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 := spacestorage.SpaceStorageCreatePayload{
AclWithId: rawAclWithId,
SpaceHeaderWithId: rawHeaderWithId,
SpaceSettingsWithId: rawSettingsPayload,
}
err = validateSpaceStorageCreatePayload(spacePayload)
assert.EqualErrorf(t, err, spacestorage.ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", spacestorage.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 := spacestorage.SpaceStorageCreatePayload{
AclWithId: rawAclWithId,
SpaceHeaderWithId: rawHeaderWithId,
SpaceSettingsWithId: rawSettingsPayload,
}
err = validateSpaceStorageCreatePayload(spacePayload)
assert.EqualErrorf(t, err, spacestorage.ErrIncorrectSpaceHeader.Error(), "Error should be: %v, got: %v", spacestorage.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()
identity, err := accountKeys.SignKey.GetPublic().Marshall()
if err != nil {
return
}
masterPubKey := masterKey.GetPublic()
rawIdentity, err := accountKeys.SignKey.GetPublic().Raw()
if err != nil {
return
}
identitySignature, err := masterKey.Sign(rawIdentity)
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 := rand.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(marhalledRawHeader)
if err != nil {
return
}
spaceId = fmt.Sprintf("%s.%s", id, strconv.FormatUint(replicationKey, 36))
rawWithId = &spacesyncproto.RawSpaceHeaderWithId{
RawHeader: marhalledRawHeader,
Id: spaceId,
}
return
}

View File

@ -80,7 +80,7 @@ func (s *spaceService) CreateSpace(ctx context.Context, payload SpaceCreatePaylo
if err != nil {
return
}
store, err := s.storageProvider.CreateSpaceStorage(storageCreate)
store, err := s.createSpaceStorage(storageCreate)
if err != nil {
if err == spacestorage.ErrSpaceStorageExists {
return storageCreate.SpaceHeaderWithId.Id, nil
@ -105,7 +105,7 @@ func (s *spaceService) DeriveSpace(ctx context.Context, payload SpaceDerivePaylo
if err != nil {
return
}
store, err := s.storageProvider.CreateSpaceStorage(storageCreate)
store, err := s.createSpaceStorage(storageCreate)
if err != nil {
if err == spacestorage.ErrSpaceStorageExists {
return storageCreate.SpaceHeaderWithId.Id, nil
@ -197,7 +197,7 @@ func (s *spaceService) addSpaceStorage(ctx context.Context, spaceDescription Spa
Id: spaceDescription.SpaceSettingsId,
},
}
st, err = s.storageProvider.CreateSpaceStorage(payload)
st, err = s.createSpaceStorage(payload)
if err != nil {
err = spacesyncproto.ErrUnexpected
if err == spacestorage.ErrSpaceStorageExists {
@ -229,7 +229,7 @@ func (s *spaceService) getSpaceStorageFromRemote(ctx context.Context, id string)
return
}
st, err = s.storageProvider.CreateSpaceStorage(spacestorage.SpaceStorageCreatePayload{
st, err = s.createSpaceStorage(spacestorage.SpaceStorageCreatePayload{
AclWithId: &aclrecordproto.RawAclRecordWithId{
Payload: res.Payload.AclPayload,
Id: res.Payload.AclPayloadId,
@ -242,3 +242,11 @@ func (s *spaceService) getSpaceStorageFromRemote(ctx context.Context, id string)
})
return
}
func (s *spaceService) createSpaceStorage(payload spacestorage.SpaceStorageCreatePayload) (spacestorage.SpaceStorage, error) {
err := validateSpaceStorageCreatePayload(payload)
if err != nil {
return nil, err
}
return s.storageProvider.CreateSpaceStorage(payload)
}

View File

@ -4,19 +4,12 @@ package spacestorage
import (
"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"
"github.com/anytypeio/any-sync/commonspace/object/tree/objecttree"
"github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto"
"github.com/anytypeio/any-sync/commonspace/object/tree/treestorage"
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
"github.com/anytypeio/any-sync/util/cidutil"
"github.com/anytypeio/any-sync/util/crypto"
"github.com/gogo/protobuf/proto"
"strconv"
"strings"
)
const CName = "common.commonspace.spacestorage"
@ -67,177 +60,3 @@ type SpaceStorageProvider interface {
SpaceExists(id string) bool
CreateSpaceStorage(payload SpaceStorageCreatePayload) (SpaceStorage, error)
}
func ValidateSpaceStorageCreatePayload(payload SpaceStorageCreatePayload) (err error) {
err = validateCreateSpaceHeaderPayload(payload.SpaceHeaderWithId)
if err != nil {
return
}
aclSpaceId, err := validateCreateSpaceAclPayload(payload.AclWithId)
if err != nil {
return
}
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
}
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(rawHeaderWithId.RawHeader, split[0]) {
err = objecttree.ErrIncorrectCid
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(rawHeaderWithId.RawHeader)
if err != nil {
return
}
requiredSpaceId := fmt.Sprintf("%s.%s", id, strconv.FormatUint(header.ReplicationKey, 36))
if requiredSpaceId != rawHeaderWithId.Id {
err = ErrIncorrectSpaceHeader
return
}
return
}
func validateCreateSpaceAclPayload(rawWithId *aclrecordproto.RawAclRecordWithId) (spaceId string, 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)
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.UnmarshalEd25519PublicKeyProto(aclRoot.MasterKey)
if err != nil {
return
}
rawIdentity, err := payloadIdentity.Raw()
if err != nil {
return
}
res, err = masterKey.Verify(rawIdentity, aclRoot.IdentitySignature)
if err != nil || !res {
err = ErrIncorrectSpaceHeader
return
}
spaceId = aclRoot.SpaceId
return
}
func validateCreateSpaceSettingsPayload(rawWithId *treechangeproto.RawTreeChangeWithId) (aclHeadId string, spaceId string, 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)
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
return
}
id, err := cidutil.NewCidFromBytes(rawWithId.RawChange)
if id != rawWithId.Id {
err = ErrIncorrectSpaceHeader
return
}
spaceId = rootChange.SpaceId
aclHeadId = rootChange.AclHeadId
return
}
// ValidateSpaceHeader Used in coordinator
func ValidateSpaceHeader(spaceId string, header []byte, identity crypto.PubKey) (err error) {
split := strings.Split(spaceId, ".")
if len(split) != 2 {
return ErrIncorrectSpaceHeader
}
if !cidutil.VerifyCid(header, split[0]) {
err = objecttree.ErrIncorrectCid
return
}
raw := &spacesyncproto.RawSpaceHeader{}
err = proto.Unmarshal(header, raw)
if err != nil {
return
}
payload := &spacesyncproto.SpaceHeader{}
err = proto.Unmarshal(raw.SpaceHeader, payload)
if err != nil {
return
}
payloadIdentity, err := crypto.UnmarshalEd25519PublicKeyProto(payload.Identity)
if err != nil {
return
}
if identity != nil && !payloadIdentity.Equals(identity) {
err = ErrIncorrectSpaceHeader
return
}
res, err := identity.Verify(raw.SpaceHeader, raw.Signature)
if err != nil || !res {
err = ErrIncorrectSpaceHeader
return
}
return
}

View File

@ -1,655 +1,2 @@
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)
_, rawHeaderWithId, err := rawHeaderWithId(accountKeys)
require.NoError(t, err)
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", ErrIncorrectSpaceHeader, 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()
spaceId := "AnySpaceId"
_, rawWithId, err := rawAclWithId(accountKeys, spaceId)
require.NoError(t, err)
validationSpaceId, err := validateCreateSpaceAclPayload(rawWithId)
require.Equal(t, validationSpaceId, spaceId)
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.GetPublic().Marshall()
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)
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)
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: 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) {
spaceId := "AnySpaceId"
accountKeys, err := accountdata.NewRandom()
require.NoError(t, err)
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
}
rawMasterKey, err := masterPubKey.Marshall()
if err != nil {
return
}
aclRoot := aclrecordproto.AclRoot{
Identity: identity,
MasterKey: rawMasterKey,
SpaceId: spaceId,
EncryptedReadKey: readKey,
Timestamp: time.Now().Unix(),
IdentitySignature: identity,
}
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,
}
_, 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)
spaceId := "SpaceId"
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,
}
_, validationSpaceId, err := validateCreateSpaceSettingsPayload(rawIdChange)
require.Equal(t, validationSpaceId, spaceId)
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)
}
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()
identity, err := accountKeys.SignKey.GetPublic().Marshall()
if err != nil {
return
}
masterPubKey := masterKey.GetPublic()
rawIdentity, err := accountKeys.SignKey.GetPublic().Raw()
if err != nil {
return
}
identitySignature, err := masterKey.Sign(rawIdentity)
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(marhalledRawHeader)
if err != nil {
return
}
spaceId = fmt.Sprintf("%s.%s", id, strconv.FormatUint(replicationKey, 36))
rawWithId = &spacesyncproto.RawSpaceHeaderWithId{
RawHeader: marhalledRawHeader,
Id: spaceId,
}
return
}