From 5baa6dc856e60d04c3b9a5e3cc46fe8aa3f11d8f Mon Sep 17 00:00:00 2001 From: mcrakhman Date: Fri, 24 Mar 2023 22:43:25 +0100 Subject: [PATCH] ACLState refactoring --- .../acl/aclrecordproto/aclreadkeyderive.go | 13 - .../object/acl/aclrecordproto/aclrecord.pb.go | 228 +++------ .../acl/aclrecordproto/protos/aclrecord.proto | 3 +- .../object/acl/list/aclrecordbuilder.go | 227 +++++---- commonspace/object/acl/list/aclstate.go | 476 ++++++++---------- commonspace/object/acl/list/list.go | 13 +- commonspace/object/acl/list/list_test.go | 14 +- commonspace/object/acl/list/models.go | 22 + commonspace/object/acl/list/record.go | 12 - .../object/tree/exporter/treeexporter.go | 2 +- commonspace/object/tree/objecttree/change.go | 4 +- .../object/tree/objecttree/changebuilder.go | 48 +- .../object/tree/objecttree/objecttree.go | 24 +- .../tree/objecttree/objecttreevalidator.go | 2 +- util/crypto/ed25519.go | 11 + util/crypto/key.go | 4 + util/crypto/keystorage.go | 9 + 17 files changed, 506 insertions(+), 606 deletions(-) delete mode 100644 commonspace/object/acl/aclrecordproto/aclreadkeyderive.go create mode 100644 commonspace/object/acl/list/models.go delete mode 100644 commonspace/object/acl/list/record.go create mode 100644 util/crypto/keystorage.go diff --git a/commonspace/object/acl/aclrecordproto/aclreadkeyderive.go b/commonspace/object/acl/aclrecordproto/aclreadkeyderive.go deleted file mode 100644 index 6d6bab90..00000000 --- a/commonspace/object/acl/aclrecordproto/aclreadkeyderive.go +++ /dev/null @@ -1,13 +0,0 @@ -package aclrecordproto - -import ( - "github.com/anytypeio/any-sync/util/crypto" - "github.com/anytypeio/any-sync/util/keys/symmetric" -) - -func AclReadKeyDerive(signKey []byte, encKey []byte) (*crypto.AESKey, error) { - concBuf := make([]byte, 0, len(signKey)+len(encKey)) - concBuf = append(concBuf, signKey...) - concBuf = append(concBuf, encKey...) - return symmetric.DeriveFromBytes(concBuf) -} diff --git a/commonspace/object/acl/aclrecordproto/aclrecord.pb.go b/commonspace/object/acl/aclrecordproto/aclrecord.pb.go index c77e7818..a8b99e7e 100644 --- a/commonspace/object/acl/aclrecordproto/aclrecord.pb.go +++ b/commonspace/object/acl/aclrecordproto/aclrecord.pb.go @@ -247,12 +247,11 @@ func (m *AclRecord) GetTimestamp() int64 { } type AclRoot struct { - Identity []byte `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` - SpaceId string `protobuf:"bytes,2,opt,name=spaceId,proto3" json:"spaceId,omitempty"` - EncryptedReadKey []byte `protobuf:"bytes,3,opt,name=encryptedReadKey,proto3" json:"encryptedReadKey,omitempty"` - DerivationScheme string `protobuf:"bytes,4,opt,name=derivationScheme,proto3" json:"derivationScheme,omitempty"` - CurrentReadKeyHash uint64 `protobuf:"varint,5,opt,name=currentReadKeyHash,proto3" json:"currentReadKeyHash,omitempty"` - Timestamp int64 `protobuf:"varint,6,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Identity []byte `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` + SpaceId string `protobuf:"bytes,2,opt,name=spaceId,proto3" json:"spaceId,omitempty"` + EncryptedReadKey []byte `protobuf:"bytes,3,opt,name=encryptedReadKey,proto3" json:"encryptedReadKey,omitempty"` + DerivationScheme string `protobuf:"bytes,4,opt,name=derivationScheme,proto3" json:"derivationScheme,omitempty"` + Timestamp int64 `protobuf:"varint,5,opt,name=timestamp,proto3" json:"timestamp,omitempty"` } func (m *AclRoot) Reset() { *m = AclRoot{} } @@ -316,13 +315,6 @@ func (m *AclRoot) GetDerivationScheme() string { return "" } -func (m *AclRoot) GetCurrentReadKeyHash() uint64 { - if m != nil { - return m.CurrentReadKeyHash - } - return 0 -} - func (m *AclRoot) GetTimestamp() int64 { if m != nil { return m.Timestamp @@ -733,10 +725,9 @@ func (m *AclUserInvite) GetPermissions() AclUserPermissions { type AclUserJoin struct { Identity []byte `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` - EncryptionKey []byte `protobuf:"bytes,2,opt,name=encryptionKey,proto3" json:"encryptionKey,omitempty"` - AcceptSignature []byte `protobuf:"bytes,3,opt,name=acceptSignature,proto3" json:"acceptSignature,omitempty"` - AcceptPubKey []byte `protobuf:"bytes,4,opt,name=acceptPubKey,proto3" json:"acceptPubKey,omitempty"` - EncryptedReadKeys [][]byte `protobuf:"bytes,5,rep,name=encryptedReadKeys,proto3" json:"encryptedReadKeys,omitempty"` + AcceptSignature []byte `protobuf:"bytes,2,opt,name=acceptSignature,proto3" json:"acceptSignature,omitempty"` + AcceptPubKey []byte `protobuf:"bytes,3,opt,name=acceptPubKey,proto3" json:"acceptPubKey,omitempty"` + EncryptedReadKeys [][]byte `protobuf:"bytes,4,rep,name=encryptedReadKeys,proto3" json:"encryptedReadKeys,omitempty"` } func (m *AclUserJoin) Reset() { *m = AclUserJoin{} } @@ -779,13 +770,6 @@ func (m *AclUserJoin) GetIdentity() []byte { return nil } -func (m *AclUserJoin) GetEncryptionKey() []byte { - if m != nil { - return m.EncryptionKey - } - return nil -} - func (m *AclUserJoin) GetAcceptSignature() []byte { if m != nil { return m.AcceptSignature @@ -1152,66 +1136,64 @@ func init() { } var fileDescriptor_c8e9f754f34e929b = []byte{ - // 943 bytes of a gzipped FileDescriptorProto + // 907 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x4f, 0x6f, 0x1b, 0x45, - 0x14, 0xf7, 0xda, 0x49, 0x1c, 0x3f, 0xbb, 0x89, 0x33, 0x40, 0xbb, 0x8a, 0x8a, 0x15, 0xad, 0x40, - 0x8a, 0xaa, 0xca, 0x11, 0x06, 0x29, 0x55, 0x84, 0xa8, 0xdc, 0x52, 0x64, 0xb7, 0x42, 0xaa, 0x26, - 0x40, 0x51, 0x39, 0x4d, 0x66, 0x47, 0xf1, 0xd0, 0xf5, 0xee, 0x6a, 0x66, 0x6c, 0xe4, 0x4f, 0x01, - 0x37, 0xae, 0x1c, 0xf9, 0x28, 0x48, 0x5c, 0x72, 0x41, 0xe2, 0x88, 0x12, 0xf1, 0x11, 0xb8, 0xa3, - 0x99, 0xd9, 0xff, 0xeb, 0x58, 0x70, 0x80, 0x43, 0xe2, 0x9d, 0xf7, 0x7e, 0xef, 0xcd, 0xef, 0xfd, - 0xe6, 0xcd, 0xdb, 0x85, 0x8f, 0x69, 0x34, 0x9f, 0x47, 0xa1, 0x8c, 0x09, 0x65, 0x27, 0xd1, 0xc5, - 0xb7, 0x8c, 0xaa, 0x13, 0x42, 0x03, 0xfd, 0x27, 0x18, 0x8d, 0x84, 0x1f, 0x8b, 0x48, 0x45, 0x27, - 0xe6, 0xbf, 0xcc, 0xad, 0x43, 0x63, 0x40, 0x9d, 0xcc, 0xe0, 0xfd, 0xe4, 0x40, 0x0f, 0x93, 0xef, - 0xc6, 0x34, 0xc0, 0xc6, 0x80, 0x5c, 0x68, 0xc7, 0x64, 0x15, 0x44, 0xc4, 0x77, 0x9d, 0x23, 0xe7, - 0xb8, 0x87, 0xd3, 0x25, 0xba, 0x0f, 0x1d, 0xc9, 0x2f, 0x43, 0xa2, 0x16, 0x82, 0xb9, 0x4d, 0xe3, - 0xcb, 0x0d, 0xe8, 0x01, 0xf4, 0x09, 0xa5, 0x2c, 0x56, 0x91, 0x98, 0xfa, 0x2c, 0x54, 0x5c, 0xad, - 0xdc, 0x96, 0x01, 0xd5, 0xec, 0xe8, 0x21, 0x1c, 0xa4, 0xb6, 0xf3, 0x2c, 0xe3, 0x96, 0x01, 0xd7, - 0x1d, 0xde, 0x27, 0x80, 0x8a, 0x0c, 0x5f, 0x71, 0x35, 0x9b, 0x6e, 0xe2, 0xb9, 0x07, 0x4d, 0xee, - 0x1b, 0x82, 0x1d, 0xdc, 0xe4, 0xbe, 0xf7, 0xbd, 0x03, 0x9d, 0xbc, 0xbe, 0xbb, 0xb0, 0x13, 0x0b, - 0xb6, 0x9c, 0xda, 0xb0, 0x0e, 0x4e, 0x56, 0xe8, 0x10, 0x76, 0x79, 0xca, 0xdb, 0x16, 0x97, 0xad, - 0x11, 0x82, 0x2d, 0x9f, 0x28, 0x92, 0xd4, 0x63, 0x9e, 0xb5, 0x1a, 0x82, 0x11, 0xff, 0x05, 0x5b, - 0x4d, 0x7d, 0xc3, 0xbd, 0x83, 0x73, 0x83, 0xf6, 0x2a, 0x3e, 0x67, 0x52, 0x91, 0x79, 0xec, 0x6e, - 0x1f, 0x39, 0xc7, 0x2d, 0x9c, 0x1b, 0xbc, 0x3f, 0x1d, 0x68, 0x6b, 0x46, 0x51, 0xa4, 0x4a, 0xfb, - 0x3a, 0x95, 0x7d, 0x5d, 0x68, 0x9b, 0x13, 0x9e, 0xa6, 0xe5, 0xa4, 0x4b, 0xad, 0x36, 0x0b, 0xa9, - 0x58, 0xc5, 0x8a, 0xf9, 0xd8, 0xee, 0x9a, 0xaa, 0x5d, 0xb5, 0x6b, 0xac, 0xcf, 0x04, 0x5f, 0x12, - 0xc5, 0xa3, 0xf0, 0x9c, 0xce, 0xd8, 0x9c, 0x25, 0x84, 0x6b, 0x76, 0x34, 0x04, 0x44, 0x17, 0x42, - 0xb0, 0x50, 0x25, 0xd1, 0x13, 0x22, 0x67, 0xa6, 0x80, 0x2d, 0xbc, 0xc6, 0x53, 0xae, 0x73, 0xa7, - 0x5a, 0xe7, 0x6f, 0x4d, 0xd8, 0x1f, 0xd3, 0xe0, 0x69, 0x14, 0x2a, 0x16, 0xaa, 0xaf, 0x48, 0xb0, - 0x60, 0xe8, 0x03, 0x68, 0x2f, 0x24, 0x13, 0x63, 0xdf, 0x1e, 0x40, 0x77, 0xf4, 0xce, 0x30, 0x6f, - 0xcf, 0x31, 0x0d, 0xbe, 0xb4, 0xce, 0x49, 0x03, 0xa7, 0x38, 0x74, 0x06, 0xa0, 0x1f, 0x31, 0x9b, - 0x47, 0x4b, 0xdb, 0x79, 0xdd, 0x91, 0x5b, 0x8f, 0xb2, 0xfe, 0x49, 0x03, 0x17, 0xd0, 0xe8, 0x6b, - 0x78, 0x5b, 0xaf, 0x5e, 0x32, 0x31, 0xe7, 0x52, 0xf2, 0x28, 0x7c, 0x3a, 0x23, 0xe1, 0x25, 0x33, - 0x62, 0x75, 0x47, 0x5e, 0x3d, 0x4b, 0x15, 0x39, 0x69, 0xe0, 0xb5, 0x19, 0x52, 0x56, 0xd3, 0x70, - 0xc9, 0x95, 0x15, 0x74, 0x2d, 0x2b, 0xeb, 0x4f, 0x59, 0xd9, 0x15, 0xfa, 0x08, 0x76, 0xf5, 0xea, - 0x79, 0xc4, 0x43, 0x23, 0x6e, 0x77, 0x74, 0xb7, 0x1e, 0xa9, 0xbd, 0x93, 0x06, 0xce, 0x90, 0x4f, - 0xda, 0xb0, 0xbd, 0xd4, 0x1a, 0x7a, 0xcf, 0x4c, 0xfb, 0x7c, 0xaa, 0xdb, 0xf0, 0x0c, 0x80, 0x64, - 0x0a, 0xbb, 0xce, 0x51, 0xeb, 0xb8, 0x3b, 0x3a, 0x2c, 0xe7, 0x2a, 0xca, 0x8f, 0x0b, 0x68, 0xef, - 0x2f, 0x07, 0x76, 0xc7, 0x34, 0x38, 0x57, 0x44, 0x31, 0x34, 0x00, 0xc8, 0xda, 0x57, 0x9a, 0x44, - 0x1d, 0x5c, 0xb0, 0xa0, 0x53, 0x5b, 0xae, 0x01, 0x4b, 0xb7, 0x69, 0x36, 0xba, 0x57, 0x27, 0x6d, - 0xfc, 0xb8, 0x00, 0x45, 0x67, 0xd0, 0xe6, 0xa6, 0x6a, 0xe9, 0xb6, 0x4c, 0xd4, 0x51, 0x39, 0xca, - 0xc0, 0x86, 0x56, 0x18, 0xf9, 0x2c, 0x54, 0x62, 0x85, 0xd3, 0x80, 0xc3, 0x2f, 0xa0, 0x57, 0x74, - 0xa0, 0x3e, 0xb4, 0xde, 0xb0, 0x55, 0x72, 0x73, 0xf5, 0x23, 0x1a, 0x26, 0x9a, 0xdc, 0xde, 0x16, - 0x36, 0x01, 0xb6, 0xb0, 0xb3, 0xe6, 0x23, 0xc7, 0x7b, 0x03, 0xbd, 0x22, 0xdb, 0x8d, 0x57, 0xf0, - 0x31, 0x74, 0xe3, 0xec, 0xe4, 0xa5, 0xd9, 0x65, 0x6f, 0xf4, 0xee, 0xa6, 0xb6, 0x91, 0xb8, 0x18, - 0xe1, 0xfd, 0xe8, 0x00, 0xe4, 0x6d, 0xbd, 0x71, 0xaf, 0x87, 0x70, 0x50, 0xbd, 0xbc, 0x56, 0xe9, - 0x1e, 0xae, 0x3b, 0xaa, 0xcc, 0x5a, 0xff, 0x9a, 0xd9, 0xcf, 0x0e, 0xdc, 0x29, 0x69, 0x84, 0x8e, - 0x61, 0xdf, 0x8e, 0xdf, 0x97, 0x8b, 0x8b, 0x80, 0xd3, 0x17, 0x2c, 0xe5, 0x58, 0x35, 0xff, 0xdf, - 0x54, 0x7f, 0x75, 0xa0, 0x5b, 0xb8, 0x15, 0x1b, 0x55, 0x7c, 0x0f, 0xee, 0x24, 0x0c, 0x78, 0x14, - 0xea, 0x12, 0xec, 0x34, 0x2f, 0x1b, 0xf3, 0x52, 0xf3, 0x17, 0x50, 0xab, 0x58, 0x6a, 0x66, 0x46, - 0x1e, 0xf4, 0xb2, 0xea, 0x75, 0x3a, 0xfb, 0x9e, 0x2a, 0xd9, 0xd6, 0xcb, 0xb1, 0x7d, 0x8b, 0x1c, - 0x9e, 0xcc, 0x74, 0x4f, 0x86, 0xd4, 0xa6, 0x72, 0x3e, 0x83, 0xfd, 0xe4, 0x16, 0x62, 0x16, 0x07, - 0x84, 0x66, 0x97, 0xef, 0x7e, 0x59, 0x3f, 0x5c, 0x02, 0xe1, 0x6a, 0x90, 0xf7, 0x0d, 0x1c, 0xd4, - 0x50, 0x1b, 0x37, 0x5e, 0xf7, 0x8a, 0x69, 0xae, 0x7f, 0xc5, 0x78, 0x4b, 0xb8, 0x77, 0xcb, 0xf8, - 0xfc, 0x6f, 0x2f, 0xd7, 0x73, 0xd8, 0xd3, 0x13, 0x64, 0x15, 0xd2, 0xcf, 0x99, 0x94, 0xe4, 0x92, - 0xa1, 0x47, 0xd0, 0xa6, 0xd9, 0x30, 0xd4, 0x13, 0x61, 0x50, 0x99, 0x36, 0xab, 0x90, 0x96, 0x06, - 0x62, 0x0a, 0xf7, 0x5e, 0xc3, 0x5b, 0x6b, 0xfc, 0x66, 0xc0, 0xfa, 0xbe, 0xfd, 0x78, 0x90, 0x49, - 0xce, 0xca, 0x94, 0x19, 0x67, 0x7e, 0x3d, 0xe6, 0x73, 0x74, 0x3e, 0xb0, 0x27, 0xe6, 0xc4, 0x73, - 0x1c, 0x3a, 0x85, 0xb6, 0xc8, 0x52, 0xea, 0xd3, 0x2c, 0x56, 0x5d, 0xff, 0xda, 0xc1, 0x29, 0xfa, - 0xc1, 0x29, 0xa0, 0xba, 0x28, 0xa8, 0x03, 0xdb, 0x63, 0x7f, 0xce, 0xc3, 0x7e, 0x03, 0x01, 0xec, - 0xbc, 0x12, 0x5c, 0x31, 0xd1, 0x77, 0xf4, 0xb3, 0x3e, 0x21, 0x26, 0xfa, 0xcd, 0x27, 0x8f, 0x7f, - 0xb9, 0x1e, 0x38, 0x57, 0xd7, 0x03, 0xe7, 0x8f, 0xeb, 0x81, 0xf3, 0xc3, 0xcd, 0xa0, 0x71, 0x75, - 0x33, 0x68, 0xfc, 0x7e, 0x33, 0x68, 0xbc, 0x7e, 0xff, 0x1f, 0x7d, 0x4b, 0x5e, 0xec, 0x98, 0x9f, - 0x0f, 0xff, 0x0e, 0x00, 0x00, 0xff, 0xff, 0xca, 0x88, 0xea, 0x1c, 0x7b, 0x0a, 0x00, 0x00, + 0x14, 0xf7, 0xd8, 0x49, 0x1c, 0x3f, 0x9b, 0xc4, 0x19, 0xa0, 0x5d, 0x45, 0xc5, 0x8a, 0x56, 0x42, + 0x8a, 0xaa, 0x2a, 0x11, 0x06, 0x29, 0x55, 0x84, 0xa8, 0xdc, 0x52, 0x64, 0xb7, 0x42, 0xaa, 0x26, + 0x40, 0x51, 0x39, 0x4d, 0x66, 0x47, 0xc9, 0xd0, 0xf5, 0xee, 0x6a, 0x66, 0x6c, 0xe4, 0x4f, 0x01, + 0x37, 0xae, 0x5c, 0x90, 0xf8, 0x02, 0x7c, 0x07, 0x8e, 0xb9, 0x20, 0x71, 0x44, 0xc9, 0x67, 0xe0, + 0x8e, 0x66, 0xc6, 0xfb, 0xdf, 0x31, 0x70, 0xa0, 0x87, 0xc4, 0x3b, 0xef, 0xfd, 0xe6, 0xcd, 0xef, + 0xfd, 0xe6, 0xbd, 0xb7, 0x0b, 0x1f, 0xb3, 0x78, 0x3a, 0x8d, 0x23, 0x95, 0x50, 0xc6, 0x8f, 0xe3, + 0xf3, 0x6f, 0x39, 0xd3, 0xc7, 0x94, 0x85, 0xe6, 0x4f, 0x72, 0x16, 0xcb, 0x20, 0x91, 0xb1, 0x8e, + 0x8f, 0xed, 0x7f, 0x95, 0x5b, 0x8f, 0xac, 0x01, 0x77, 0x32, 0x83, 0xff, 0x13, 0x82, 0x1e, 0xa1, + 0xdf, 0x8d, 0x58, 0x48, 0xac, 0x01, 0x7b, 0xd0, 0x4e, 0xe8, 0x22, 0x8c, 0x69, 0xe0, 0xa1, 0x03, + 0x74, 0xd8, 0x23, 0xe9, 0x12, 0xdf, 0x83, 0x8e, 0x12, 0x17, 0x11, 0xd5, 0x33, 0xc9, 0xbd, 0xa6, + 0xf5, 0xe5, 0x06, 0x7c, 0x1f, 0xfa, 0x94, 0x31, 0x9e, 0xe8, 0x58, 0x4e, 0x02, 0x1e, 0x69, 0xa1, + 0x17, 0x5e, 0xcb, 0x82, 0x6a, 0x76, 0xfc, 0x00, 0xf6, 0x52, 0xdb, 0x59, 0x16, 0x71, 0xc3, 0x82, + 0xeb, 0x0e, 0xff, 0x13, 0xc0, 0x45, 0x86, 0x2f, 0x85, 0xbe, 0x9c, 0xac, 0xe3, 0xb9, 0x03, 0x4d, + 0x11, 0x58, 0x82, 0x1d, 0xd2, 0x14, 0x81, 0xff, 0x3d, 0x82, 0x4e, 0x9e, 0xdf, 0x1d, 0xd8, 0x4a, + 0x24, 0x9f, 0x4f, 0xdc, 0xb6, 0x0e, 0x59, 0xae, 0xf0, 0x3e, 0x6c, 0x8b, 0x94, 0xb7, 0x4b, 0x2e, + 0x5b, 0x63, 0x0c, 0x1b, 0x01, 0xd5, 0x74, 0x99, 0x8f, 0x7d, 0x36, 0x6a, 0x48, 0x4e, 0x83, 0xe7, + 0x7c, 0x31, 0x09, 0x2c, 0xf7, 0x0e, 0xc9, 0x0d, 0xc6, 0xab, 0xc5, 0x94, 0x2b, 0x4d, 0xa7, 0x89, + 0xb7, 0x79, 0x80, 0x0e, 0x5b, 0x24, 0x37, 0xf8, 0xbf, 0x22, 0x68, 0x1b, 0x46, 0x71, 0xac, 0x4b, + 0xe7, 0xa2, 0xca, 0xb9, 0x1e, 0xb4, 0xed, 0x0d, 0x4f, 0xd2, 0x74, 0xd2, 0xa5, 0x51, 0x9b, 0x47, + 0x4c, 0x2e, 0x12, 0xcd, 0x03, 0xe2, 0x4e, 0x4d, 0xd5, 0xae, 0xda, 0x0d, 0x36, 0xe0, 0x52, 0xcc, + 0xa9, 0x16, 0x71, 0x74, 0xc6, 0x2e, 0xf9, 0x94, 0x2f, 0x09, 0xd7, 0xec, 0xff, 0xc0, 0xfb, 0xf7, + 0x26, 0xec, 0x8e, 0x58, 0xf8, 0x24, 0x8e, 0x34, 0x8f, 0xf4, 0x57, 0x34, 0x9c, 0x71, 0xfc, 0x01, + 0xb4, 0x67, 0x8a, 0xcb, 0x51, 0xe0, 0x04, 0xed, 0x0e, 0xdf, 0x3d, 0xca, 0xcb, 0x6d, 0xc4, 0xc2, + 0x2f, 0x9d, 0x73, 0xdc, 0x20, 0x29, 0x0e, 0x9f, 0x02, 0x98, 0x47, 0xc2, 0xa7, 0xf1, 0xdc, 0x55, + 0x52, 0x77, 0xe8, 0xd5, 0x77, 0x39, 0xff, 0xb8, 0x41, 0x0a, 0x68, 0xfc, 0x35, 0xbc, 0x63, 0x56, + 0x2f, 0xb8, 0x9c, 0x0a, 0xa5, 0x44, 0x1c, 0x3d, 0xb9, 0xa4, 0xd1, 0x05, 0xb7, 0xc9, 0x77, 0x87, + 0x7e, 0x3d, 0x4a, 0x15, 0x39, 0x6e, 0x90, 0x95, 0x11, 0x52, 0x56, 0x93, 0x68, 0x2e, 0xb4, 0x13, + 0x68, 0x25, 0x2b, 0xe7, 0x4f, 0x59, 0xb9, 0x15, 0xfe, 0x08, 0xb6, 0xcd, 0xea, 0x59, 0x2c, 0x22, + 0xab, 0x5a, 0x77, 0x78, 0xa7, 0xbe, 0xd3, 0x78, 0xc7, 0x0d, 0x92, 0x21, 0x1f, 0xb7, 0x61, 0x73, + 0x6e, 0x34, 0xf4, 0x9f, 0xda, 0x72, 0xf8, 0xd4, 0x94, 0xd5, 0x29, 0x00, 0xcd, 0x14, 0xf6, 0xd0, + 0x41, 0xeb, 0xb0, 0x3b, 0xdc, 0x2f, 0xc7, 0x2a, 0xca, 0x4f, 0x0a, 0x68, 0xff, 0x2f, 0x04, 0xdb, + 0x23, 0x16, 0x9e, 0x69, 0xaa, 0x39, 0x1e, 0x00, 0x64, 0xe5, 0xa8, 0x6c, 0xa0, 0x0e, 0x29, 0x58, + 0xf0, 0x89, 0x4b, 0xd7, 0x82, 0x95, 0xd7, 0xb4, 0x07, 0xdd, 0xad, 0x93, 0xb6, 0x7e, 0x52, 0x80, + 0xe2, 0x53, 0x68, 0x0b, 0x9b, 0xb5, 0xf2, 0x5a, 0x76, 0xd7, 0x41, 0x79, 0x97, 0x85, 0x1d, 0x39, + 0x61, 0xd4, 0xd3, 0x48, 0xcb, 0x05, 0x49, 0x37, 0xec, 0x7f, 0x01, 0xbd, 0xa2, 0x03, 0xf7, 0xa1, + 0xf5, 0x9a, 0x2f, 0x96, 0x9d, 0x68, 0x1e, 0xf1, 0xd1, 0x52, 0x93, 0xdb, 0xcb, 0xc2, 0x05, 0x20, + 0x0e, 0x76, 0xda, 0x7c, 0x88, 0xfc, 0xd7, 0xd0, 0x2b, 0xb2, 0x5d, 0xdb, 0x52, 0x8f, 0xa0, 0x9b, + 0x64, 0x37, 0xaf, 0xec, 0x29, 0x3b, 0xc3, 0xf7, 0xd6, 0x95, 0x8d, 0x22, 0xc5, 0x1d, 0xfe, 0x8f, + 0x08, 0x20, 0x2f, 0xeb, 0xb5, 0x67, 0x3d, 0x80, 0xbd, 0x6a, 0x33, 0x3a, 0xa5, 0x7b, 0xa4, 0xee, + 0xa8, 0x32, 0x6b, 0xfd, 0x67, 0x66, 0xbf, 0x20, 0x78, 0xab, 0xa4, 0x11, 0x3e, 0x84, 0x5d, 0x37, + 0x4e, 0x5f, 0xcc, 0xce, 0x43, 0xc1, 0x9e, 0xf3, 0x94, 0x63, 0xd5, 0xfc, 0xa6, 0xa9, 0xfe, 0x8c, + 0xa0, 0x5b, 0xe8, 0x8a, 0xb5, 0x2a, 0x66, 0x49, 0x9c, 0x55, 0x5e, 0x3e, 0x55, 0x33, 0xf6, 0xa1, + 0x97, 0xe5, 0x95, 0x0f, 0xc4, 0x92, 0x6d, 0x75, 0xa2, 0x1b, 0xb7, 0x24, 0xea, 0xab, 0x4c, 0xd1, + 0xe5, 0xf8, 0x59, 0x47, 0xf4, 0x33, 0xd8, 0x5d, 0xf6, 0x17, 0xe1, 0x49, 0x48, 0x59, 0xd6, 0x56, + 0xf7, 0xca, 0xca, 0x90, 0x12, 0x88, 0x54, 0x37, 0xf9, 0xdf, 0xc0, 0x5e, 0x0d, 0xb5, 0xf6, 0xe0, + 0x55, 0x2f, 0x83, 0xe6, 0xea, 0x97, 0x81, 0x3f, 0x87, 0xbb, 0xb7, 0x0c, 0xc6, 0xff, 0xb7, 0x6d, + 0x9e, 0xc1, 0x8e, 0x99, 0x0d, 0x8b, 0x88, 0x7d, 0xce, 0x95, 0xa2, 0x17, 0x1c, 0x3f, 0x84, 0x36, + 0xcb, 0xc6, 0x9c, 0xe9, 0xf5, 0x41, 0x65, 0x8e, 0x2c, 0x22, 0x56, 0x1a, 0x75, 0x29, 0xdc, 0x7f, + 0x05, 0x6f, 0xaf, 0xf0, 0xdb, 0xd1, 0x19, 0x04, 0xee, 0x35, 0xaf, 0x96, 0x31, 0x2b, 0xf3, 0x63, + 0x94, 0xf9, 0xcd, 0x00, 0xcf, 0xd1, 0xf9, 0x28, 0x1e, 0xdb, 0x1b, 0xcf, 0x71, 0xf8, 0x04, 0xda, + 0x32, 0x0b, 0x69, 0x6e, 0xb3, 0x98, 0x75, 0xfd, 0xbb, 0x84, 0xa4, 0xe8, 0xfb, 0x27, 0x80, 0xeb, + 0xa2, 0xe0, 0x0e, 0x6c, 0x8e, 0x82, 0xa9, 0x88, 0xfa, 0x0d, 0x0c, 0xb0, 0xf5, 0x52, 0x0a, 0xcd, + 0x65, 0x1f, 0x99, 0x67, 0x73, 0x43, 0x5c, 0xf6, 0x9b, 0x8f, 0x1f, 0xfd, 0x76, 0x3d, 0x40, 0x57, + 0xd7, 0x03, 0xf4, 0xe7, 0xf5, 0x00, 0xfd, 0x70, 0x33, 0x68, 0x5c, 0xdd, 0x0c, 0x1a, 0x7f, 0xdc, + 0x0c, 0x1a, 0xaf, 0xde, 0xff, 0x57, 0x5f, 0x7d, 0xe7, 0x5b, 0xf6, 0xe7, 0xc3, 0xbf, 0x03, 0x00, + 0x00, 0xff, 0xff, 0x34, 0xb4, 0xa5, 0x8e, 0x25, 0x0a, 0x00, 0x00, } func (m *RawAclRecord) Marshal() (dAtA []byte, err error) { @@ -1381,11 +1363,6 @@ func (m *AclRoot) MarshalToSizedBuffer(dAtA []byte) (int, error) { if m.Timestamp != 0 { i = encodeVarintAclrecord(dAtA, i, uint64(m.Timestamp)) i-- - dAtA[i] = 0x30 - } - if m.CurrentReadKeyHash != 0 { - i = encodeVarintAclrecord(dAtA, i, uint64(m.CurrentReadKeyHash)) - i-- dAtA[i] = 0x28 } if len(m.DerivationScheme) > 0 { @@ -1814,7 +1791,7 @@ func (m *AclUserJoin) MarshalToSizedBuffer(dAtA []byte) (int, error) { copy(dAtA[i:], m.EncryptedReadKeys[iNdEx]) i = encodeVarintAclrecord(dAtA, i, uint64(len(m.EncryptedReadKeys[iNdEx]))) i-- - dAtA[i] = 0x2a + dAtA[i] = 0x22 } } if len(m.AcceptPubKey) > 0 { @@ -1822,20 +1799,13 @@ func (m *AclUserJoin) MarshalToSizedBuffer(dAtA []byte) (int, error) { copy(dAtA[i:], m.AcceptPubKey) i = encodeVarintAclrecord(dAtA, i, uint64(len(m.AcceptPubKey))) i-- - dAtA[i] = 0x22 + dAtA[i] = 0x1a } if len(m.AcceptSignature) > 0 { i -= len(m.AcceptSignature) copy(dAtA[i:], m.AcceptSignature) i = encodeVarintAclrecord(dAtA, i, uint64(len(m.AcceptSignature))) i-- - dAtA[i] = 0x1a - } - if len(m.EncryptionKey) > 0 { - i -= len(m.EncryptionKey) - copy(dAtA[i:], m.EncryptionKey) - i = encodeVarintAclrecord(dAtA, i, uint64(len(m.EncryptionKey))) - i-- dAtA[i] = 0x12 } if len(m.Identity) > 0 { @@ -2192,9 +2162,6 @@ func (m *AclRoot) Size() (n int) { if l > 0 { n += 1 + l + sovAclrecord(uint64(l)) } - if m.CurrentReadKeyHash != 0 { - n += 1 + sovAclrecord(uint64(m.CurrentReadKeyHash)) - } if m.Timestamp != 0 { n += 1 + sovAclrecord(uint64(m.Timestamp)) } @@ -2392,10 +2359,6 @@ func (m *AclUserJoin) Size() (n int) { if l > 0 { n += 1 + l + sovAclrecord(uint64(l)) } - l = len(m.EncryptionKey) - if l > 0 { - n += 1 + l + sovAclrecord(uint64(l)) - } l = len(m.AcceptSignature) if l > 0 { n += 1 + l + sovAclrecord(uint64(l)) @@ -3188,25 +3151,6 @@ func (m *AclRoot) Unmarshal(dAtA []byte) error { m.DerivationScheme = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field CurrentReadKeyHash", wireType) - } - m.CurrentReadKeyHash = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowAclrecord - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.CurrentReadKeyHash |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 6: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) } @@ -4237,40 +4181,6 @@ func (m *AclUserJoin) Unmarshal(dAtA []byte) error { } iNdEx = postIndex case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field EncryptionKey", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowAclrecord - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthAclrecord - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthAclrecord - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.EncryptionKey = append(m.EncryptionKey[:0], dAtA[iNdEx:postIndex]...) - if m.EncryptionKey == nil { - m.EncryptionKey = []byte{} - } - iNdEx = postIndex - case 3: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field AcceptSignature", wireType) } @@ -4304,7 +4214,7 @@ func (m *AclUserJoin) Unmarshal(dAtA []byte) error { m.AcceptSignature = []byte{} } iNdEx = postIndex - case 4: + case 3: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field AcceptPubKey", wireType) } @@ -4338,7 +4248,7 @@ func (m *AclUserJoin) Unmarshal(dAtA []byte) error { m.AcceptPubKey = []byte{} } iNdEx = postIndex - case 5: + case 4: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field EncryptedReadKeys", wireType) } diff --git a/commonspace/object/acl/aclrecordproto/protos/aclrecord.proto b/commonspace/object/acl/aclrecordproto/protos/aclrecord.proto index 72101d15..4a6658d5 100644 --- a/commonspace/object/acl/aclrecordproto/protos/aclrecord.proto +++ b/commonspace/object/acl/aclrecordproto/protos/aclrecord.proto @@ -27,8 +27,7 @@ message AclRoot { string spaceId = 2; bytes encryptedReadKey = 3; string derivationScheme = 4; - uint64 currentReadKeyHash = 5; - int64 timestamp = 6; + int64 timestamp = 5; } message AclContentValue { diff --git a/commonspace/object/acl/list/aclrecordbuilder.go b/commonspace/object/acl/list/aclrecordbuilder.go index 4a68ce77..e85f6be1 100644 --- a/commonspace/object/acl/list/aclrecordbuilder.go +++ b/commonspace/object/acl/list/aclrecordbuilder.go @@ -2,129 +2,131 @@ package list import ( "github.com/anytypeio/any-sync/commonspace/object/acl/aclrecordproto" - "github.com/anytypeio/any-sync/commonspace/object/keychain" "github.com/anytypeio/any-sync/util/cidutil" "github.com/anytypeio/any-sync/util/crypto" "github.com/gogo/protobuf/proto" - "time" ) -// remove interface type AclRecordBuilder interface { - ConvertFromRaw(rawIdRecord *aclrecordproto.RawAclRecordWithId) (rec *AclRecord, err error) - BuildUserJoin(acceptPrivKeyBytes []byte, encSymKeyBytes []byte, state *AclState) (rec *aclrecordproto.RawAclRecord, err error) + FromRaw(rawIdRecord *aclrecordproto.RawAclRecordWithId) (rec *AclRecord, err error) } type aclRecordBuilder struct { - id string - keychain *keychain.Keychain + id string + keyStorage crypto.KeyStorage } -func newAclRecordBuilder(id string, keychain *keychain.Keychain) AclRecordBuilder { +func newAclRecordBuilder(id string, keyStorage crypto.KeyStorage) AclRecordBuilder { return &aclRecordBuilder{ - id: id, - keychain: keychain, + id: id, + keyStorage: keyStorage, } } -func (a *aclRecordBuilder) BuildUserJoin(acceptPrivKeyBytes []byte, encSymKeyBytes []byte, state *AclState) (rec *aclrecordproto.RawAclRecord, err error) { - acceptPrivKey, err := crypto.NewSigningEd25519PrivKeyFromBytes(acceptPrivKeyBytes) - if err != nil { - return - } - acceptPubKeyBytes, err := acceptPrivKey.GetPublic().Raw() - if err != nil { - return - } - encSymKey, err := crypto.UnmarshallAESKey(encSymKeyBytes) - if err != nil { - return - } +// TODO: update with new logic +//func (a *aclRecordBuilder) BuildUserJoin(acceptPrivKeyBytes []byte, encSymKeyBytes []byte, state *AclState) (rec *aclrecordproto.RawAclRecord, err error) { +// acceptPrivKey, err := crypto.NewSigningEd25519PrivKeyFromBytes(acceptPrivKeyBytes) +// if err != nil { +// return +// } +// acceptPubKeyBytes, err := acceptPrivKey.GetPublic().Raw() +// if err != nil { +// return +// } +// encSymKey, err := crypto.UnmarshallAESKey(encSymKeyBytes) +// if err != nil { +// return +// } +// +// invite, err := state.Invite(acceptPubKeyBytes) +// if err != nil { +// return +// } +// +// encPrivKey, signPrivKey := state.UserKeys() +// var symKeys [][]byte +// for _, rk := range invite.EncryptedReadKeys { +// dec, err := encSymKey.Decrypt(rk) +// if err != nil { +// return nil, err +// } +// newEnc, err := encPrivKey.GetPublic().Encrypt(dec) +// if err != nil { +// return nil, err +// } +// symKeys = append(symKeys, newEnc) +// } +// idSignature, err := acceptPrivKey.Sign(state.Identity()) +// if err != nil { +// return +// } +// encPubKeyBytes, err := encPrivKey.GetPublic().Raw() +// if err != nil { +// return +// } +// +// userJoin := &aclrecordproto.AclUserJoin{ +// Identity: state.Identity(), +// EncryptionKey: encPubKeyBytes, +// AcceptSignature: idSignature, +// AcceptPubKey: acceptPubKeyBytes, +// EncryptedReadKeys: symKeys, +// } +// aclData := &aclrecordproto.AclData{AclContent: []*aclrecordproto.AclContentValue{ +// {Value: &aclrecordproto.AclContentValue_UserJoin{UserJoin: userJoin}}, +// }} +// marshalledJoin, err := aclData.Marshal() +// if err != nil { +// return +// } +// aclRecord := &aclrecordproto.AclRecord{ +// PrevId: state.LastRecordId(), +// Identity: state.Identity(), +// Data: marshalledJoin, +// CurrentReadKeyHash: state.CurrentReadKeyId(), +// Timestamp: time.Now().Unix(), +// } +// marshalledRecord, err := aclRecord.Marshal() +// if err != nil { +// return +// } +// recSignature, err := signPrivKey.Sign(marshalledRecord) +// if err != nil { +// return +// } +// rec = &aclrecordproto.RawAclRecord{ +// Payload: marshalledRecord, +// Signature: recSignature, +// } +// return +//} - invite, err := state.Invite(acceptPubKeyBytes) - if err != nil { - return - } - - encPrivKey, signPrivKey := state.UserKeys() - var symKeys [][]byte - for _, rk := range invite.EncryptedReadKeys { - dec, err := encSymKey.Decrypt(rk) - if err != nil { - return nil, err - } - newEnc, err := encPrivKey.GetPublic().Encrypt(dec) - if err != nil { - return nil, err - } - symKeys = append(symKeys, newEnc) - } - idSignature, err := acceptPrivKey.Sign(state.Identity()) - if err != nil { - return - } - encPubKeyBytes, err := encPrivKey.GetPublic().Raw() - if err != nil { - return - } - - userJoin := &aclrecordproto.AclUserJoin{ - Identity: state.Identity(), - EncryptionKey: encPubKeyBytes, - AcceptSignature: idSignature, - AcceptPubKey: acceptPubKeyBytes, - EncryptedReadKeys: symKeys, - } - aclData := &aclrecordproto.AclData{AclContent: []*aclrecordproto.AclContentValue{ - {Value: &aclrecordproto.AclContentValue_UserJoin{UserJoin: userJoin}}, - }} - marshalledJoin, err := aclData.Marshal() - if err != nil { - return - } - aclRecord := &aclrecordproto.AclRecord{ - PrevId: state.LastRecordId(), - Identity: state.Identity(), - Data: marshalledJoin, - CurrentReadKeyHash: state.CurrentReadKeyHash(), - Timestamp: time.Now().Unix(), - } - marshalledRecord, err := aclRecord.Marshal() - if err != nil { - return - } - recSignature, err := signPrivKey.Sign(marshalledRecord) - if err != nil { - return - } - rec = &aclrecordproto.RawAclRecord{ - Payload: marshalledRecord, - Signature: recSignature, - } - return -} - -func (a *aclRecordBuilder) ConvertFromRaw(rawIdRecord *aclrecordproto.RawAclRecordWithId) (rec *AclRecord, err error) { - rawRec := &aclrecordproto.RawAclRecord{} +func (a *aclRecordBuilder) FromRaw(rawIdRecord *aclrecordproto.RawAclRecordWithId) (rec *AclRecord, err error) { + var ( + rawRec = &aclrecordproto.RawAclRecord{} + pubKey crypto.PubKey + ) err = proto.Unmarshal(rawIdRecord.Payload, rawRec) if err != nil { return } - if rawIdRecord.Id == a.id { aclRoot := &aclrecordproto.AclRoot{} err = proto.Unmarshal(rawRec.Payload, aclRoot) if err != nil { return } - + pubKey, err = a.keyStorage.PubKeyFromProto(aclRoot.Identity) + if err != nil { + return + } rec = &AclRecord{ - Id: rawIdRecord.Id, - CurrentReadKeyHash: aclRoot.CurrentReadKeyHash, - Timestamp: aclRoot.Timestamp, - Signature: rawRec.Signature, - Identity: aclRoot.Identity, - Model: aclRoot, + Id: rawIdRecord.Id, + ReadKeyId: rawIdRecord.Id, + Timestamp: aclRoot.Timestamp, + Signature: rawRec.Signature, + Identity: pubKey, + Model: aclRoot, } } else { aclRecord := &aclrecordproto.AclRecord{} @@ -132,34 +134,31 @@ func (a *aclRecordBuilder) ConvertFromRaw(rawIdRecord *aclrecordproto.RawAclReco if err != nil { return } - + pubKey, err = a.keyStorage.PubKeyFromProto(aclRecord.Identity) + if err != nil { + return + } rec = &AclRecord{ - Id: rawIdRecord.Id, - PrevId: aclRecord.PrevId, - CurrentReadKeyHash: aclRecord.CurrentReadKeyHash, - Timestamp: aclRecord.Timestamp, - Data: aclRecord.Data, - Signature: rawRec.Signature, - Identity: aclRecord.Identity, + Id: rawIdRecord.Id, + PrevId: aclRecord.PrevId, + ReadKeyId: aclRecord.ReadKeyId, + Timestamp: aclRecord.Timestamp, + Data: aclRecord.Data, + Signature: rawRec.Signature, + Identity: pubKey, } } - err = verifyRaw(a.keychain, rawRec, rawIdRecord, rec.Identity) + err = verifyRaw(pubKey, rawRec, rawIdRecord) return } func verifyRaw( - keychain *keychain.Keychain, + pubKey crypto.PubKey, rawRec *aclrecordproto.RawAclRecord, - recWithId *aclrecordproto.RawAclRecordWithId, - identity []byte) (err error) { - identityKey, err := keychain.GetOrAdd(string(identity)) - if err != nil { - return - } - + recWithId *aclrecordproto.RawAclRecordWithId) (err error) { // verifying signature - res, err := identityKey.Verify(rawRec.Payload, rawRec.Signature) + res, err := pubKey.Verify(rawRec.Payload, rawRec.Signature) if err != nil { return } diff --git a/commonspace/object/acl/list/aclstate.go b/commonspace/object/acl/list/aclstate.go index a0426b42..4c4e4de9 100644 --- a/commonspace/object/acl/list/aclstate.go +++ b/commonspace/object/acl/list/aclstate.go @@ -1,18 +1,13 @@ package list import ( - "bytes" "errors" "fmt" - "hash/fnv" "github.com/anytypeio/any-sync/app/logger" "github.com/anytypeio/any-sync/commonspace/object/acl/aclrecordproto" "github.com/anytypeio/any-sync/commonspace/object/keychain" "github.com/anytypeio/any-sync/util/crypto" - "github.com/anytypeio/any-sync/util/keys" - "github.com/anytypeio/any-sync/util/keys/asymmetric/encryptionkey" - "github.com/anytypeio/any-sync/util/keys/asymmetric/signingkey" "github.com/gogo/protobuf/proto" "go.uber.org/zap" ) @@ -36,86 +31,80 @@ var ( ) type UserPermissionPair struct { - Identity string + Identity crypto.PubKey Permission aclrecordproto.AclUserPermissions } type AclState struct { - id string - currentReadKeyHash uint64 - userReadKeys map[uint64]*crypto.AESKey - userStates map[string]*aclrecordproto.AclUserState - userInvites map[string]*aclrecordproto.AclUserInvite - encryptionKey encryptionkey.PrivKey - signingKey signingkey.PrivKey - totalReadKeys int + id string + currentReadKeyId string + userReadKeys map[string]crypto.SymKey + userStates map[string]AclUserState + statesAtRecord map[string][]AclUserState + //userInvites map[string]*aclrecordproto.AclUserInvite + key crypto.PrivKey + pubKey crypto.PubKey + keyStore crypto.KeyStorage + totalReadKeys int - identity string - permissionsAtRecord map[string][]UserPermissionPair - lastRecordId string + lastRecordId string keychain *keychain.Keychain } func newAclStateWithKeys( id string, - signingKey signingkey.PrivKey, - encryptionKey encryptionkey.PrivKey) (*AclState, error) { - identity, err := signingKey.GetPublic().Raw() - if err != nil { - return nil, err - } + key crypto.PrivKey) (*AclState, error) { return &AclState{ - id: id, - identity: string(identity), - signingKey: signingKey, - encryptionKey: encryptionKey, - userReadKeys: make(map[uint64]*crypto.AESKey), - userStates: make(map[string]*aclrecordproto.AclUserState), - userInvites: make(map[string]*aclrecordproto.AclUserInvite), - permissionsAtRecord: make(map[string][]UserPermissionPair), + id: id, + key: key, + pubKey: key.GetPublic(), + userReadKeys: make(map[string]crypto.SymKey), + userStates: make(map[string]AclUserState), + statesAtRecord: make(map[string][]AclUserState), + //userInvites: make(map[string]*aclrecordproto.AclUserInvite), }, nil } func newAclState(id string) *AclState { return &AclState{ - id: id, - userReadKeys: make(map[uint64]*crypto.AESKey), - userStates: make(map[string]*aclrecordproto.AclUserState), - userInvites: make(map[string]*aclrecordproto.AclUserInvite), - permissionsAtRecord: make(map[string][]UserPermissionPair), + id: id, + userReadKeys: make(map[string]crypto.SymKey), + userStates: make(map[string]AclUserState), + statesAtRecord: make(map[string][]AclUserState), + //userInvites: make(map[string]*aclrecordproto.AclUserInvite), } } -func (st *AclState) CurrentReadKeyHash() uint64 { - return st.currentReadKeyHash +func (st *AclState) CurrentReadKeyId() string { + return st.currentReadKeyId } -func (st *AclState) CurrentReadKey() (*crypto.AESKey, error) { - key, exists := st.userReadKeys[st.currentReadKeyHash] +func (st *AclState) CurrentReadKey() (crypto.SymKey, error) { + key, exists := st.userReadKeys[st.currentReadKeyId] if !exists { return nil, ErrNoReadKey } return key, nil } -func (st *AclState) UserReadKeys() map[uint64]*crypto.AESKey { +func (st *AclState) UserReadKeys() map[string]crypto.SymKey { return st.userReadKeys } -func (st *AclState) PermissionsAtRecord(id string, identity string) (UserPermissionPair, error) { - permissions, ok := st.permissionsAtRecord[id] +func (st *AclState) StateAtRecord(id string, pubKey crypto.PubKey) (AclUserState, error) { + userState, ok := st.statesAtRecord[id] if !ok { log.Errorf("missing record at id %s", id) - return UserPermissionPair{}, ErrNoSuchRecord + return AclUserState{}, ErrNoSuchRecord } - for _, perm := range permissions { - if perm.Identity == identity { + for _, perm := range userState { + if perm.PubKey.Equals(pubKey) { return perm, nil } } - return UserPermissionPair{}, ErrNoSuchUser + return AclUserState{}, ErrNoSuchUser } func (st *AclState) applyRecord(record *AclRecord) (err error) { @@ -129,24 +118,18 @@ func (st *AclState) applyRecord(record *AclRecord) (err error) { return } if record.Id == st.id { - root, ok := record.Model.(*aclrecordproto.AclRoot) - if !ok { - return ErrIncorrectRoot - } - err = st.applyRoot(root) + err = st.applyRoot(record) if err != nil { return } - st.permissionsAtRecord[record.Id] = []UserPermissionPair{ - {Identity: string(root.Identity), Permission: aclrecordproto.AclUserPermissions_Admin}, + st.statesAtRecord[record.Id] = []AclUserState{ + {PubKey: record.Identity, Permissions: aclrecordproto.AclUserPermissions_Admin}, } return } - aclData := &aclrecordproto.AclData{} - if record.Model != nil { - aclData = record.Model.(*aclrecordproto.AclData) - } else { + if record.Model == nil { + aclData := &aclrecordproto.AclData{} err = proto.Unmarshal(record.Data, aclData) if err != nil { return @@ -154,109 +137,96 @@ func (st *AclState) applyRecord(record *AclRecord) (err error) { record.Model = aclData } - err = st.applyChangeData(aclData, record.CurrentReadKeyHash, record.Identity) + err = st.applyChangeData(record) if err != nil { return } - // getting all permissions for users at record - var permissions []UserPermissionPair + // getting all states for users at record + var states []AclUserState for _, state := range st.userStates { - permission := UserPermissionPair{ - Identity: string(state.Identity), - Permission: state.Permissions, - } - permissions = append(permissions, permission) + states = append(states, state) } - st.permissionsAtRecord[record.Id] = permissions + st.statesAtRecord[record.Id] = states return } -func (st *AclState) applyRoot(root *aclrecordproto.AclRoot) (err error) { - if st.signingKey != nil && st.encryptionKey != nil && st.identity == string(root.Identity) { - err = st.saveReadKeyFromRoot(root) +func (st *AclState) applyRoot(record *AclRecord) (err error) { + if st.key != nil && st.pubKey.Equals(record.Identity) { + err = st.saveReadKeyFromRoot(record) if err != nil { return } } // adding user to the list - userState := &aclrecordproto.AclUserState{ - Identity: root.Identity, - EncryptionKey: root.EncryptionKey, - Permissions: aclrecordproto.AclUserPermissions_Admin, + userState := AclUserState{ + PubKey: record.Identity, + Permissions: aclrecordproto.AclUserPermissions_Admin, } - st.currentReadKeyHash = root.CurrentReadKeyHash - st.userStates[string(root.Identity)] = userState + st.currentReadKeyId = record.ReadKeyId + st.userStates[mapKeyFromPubKey(record.Identity)] = userState st.totalReadKeys++ return } -func (st *AclState) saveReadKeyFromRoot(root *aclrecordproto.AclRoot) (err error) { - var readKey *crypto.AESKey +func (st *AclState) saveReadKeyFromRoot(record *AclRecord) (err error) { + var readKey crypto.SymKey + root, ok := record.Model.(*aclrecordproto.AclRoot) + if !ok { + return ErrIncorrectRoot + } if len(root.GetDerivationScheme()) != 0 { - var encPrivKey []byte - encPrivKey, err = st.encryptionKey.Raw() - if err != nil { - return - } - var signPrivKey []byte - signPrivKey, err = st.signingKey.Raw() + var keyBytes []byte + keyBytes, err = st.key.Raw() if err != nil { return } - readKey, err = aclrecordproto.AclReadKeyDerive(signPrivKey, encPrivKey) + readKey, err = crypto.DeriveAccountSymmetric(keyBytes) if err != nil { return } } else { - readKey, _, err = st.decryptReadKeyAndHash(root.EncryptedReadKey) + readKey, err = st.decryptReadKey(root.EncryptedReadKey) if err != nil { return } } - hasher := fnv.New64() - _, err = hasher.Write(readKey.Bytes()) - if err != nil { - return - } - if hasher.Sum64() != root.CurrentReadKeyHash { - return ErrIncorrectRoot - } - st.userReadKeys[root.CurrentReadKeyHash] = readKey - + st.userReadKeys[record.Id] = readKey return } -func (st *AclState) applyChangeData(changeData *aclrecordproto.AclData, hash uint64, identity []byte) (err error) { +func (st *AclState) applyChangeData(record *AclRecord) (err error) { defer func() { if err != nil { return } - if hash != st.currentReadKeyHash { + if record.ReadKeyId != st.currentReadKeyId { st.totalReadKeys++ - st.currentReadKeyHash = hash + st.currentReadKeyId = record.ReadKeyId } }() - - if !st.isUserJoin(changeData) { + model := record.Model.(*aclrecordproto.AclData) + if !st.isUserJoin(model) { // we check signature when we add this to the List, so no need to do it here - if _, exists := st.userStates[string(identity)]; !exists { + if _, exists := st.userStates[mapKeyFromPubKey(record.Identity)]; !exists { err = ErrNoSuchUser return } - if !st.HasPermission(identity, aclrecordproto.AclUserPermissions_Admin) { - err = fmt.Errorf("user %s must have admin permissions", identity) + // only Admins can do non-user join changes + if !st.HasPermission(record.Identity, aclrecordproto.AclUserPermissions_Admin) { + // TODO: add string encoding + err = fmt.Errorf("user %s must have admin permissions", record.Identity.String()) return } } - for _, ch := range changeData.GetAclContent() { - if err = st.applyChangeContent(ch); err != nil { + for _, ch := range model.GetAclContent() { + if err = st.applyChangeContent(ch, record.Id); err != nil { log.Info("error while applying changes: %v; ignore", zap.Error(err)) return err } @@ -265,26 +235,29 @@ func (st *AclState) applyChangeData(changeData *aclrecordproto.AclData, hash uin return nil } -func (st *AclState) applyChangeContent(ch *aclrecordproto.AclContentValue) error { +func (st *AclState) applyChangeContent(ch *aclrecordproto.AclContentValue, recordId string) error { switch { case ch.GetUserPermissionChange() != nil: - return st.applyUserPermissionChange(ch.GetUserPermissionChange()) + return st.applyUserPermissionChange(ch.GetUserPermissionChange(), recordId) case ch.GetUserAdd() != nil: - return st.applyUserAdd(ch.GetUserAdd()) + return st.applyUserAdd(ch.GetUserAdd(), recordId) case ch.GetUserRemove() != nil: - return st.applyUserRemove(ch.GetUserRemove()) + return st.applyUserRemove(ch.GetUserRemove(), recordId) case ch.GetUserInvite() != nil: - return st.applyUserInvite(ch.GetUserInvite()) + return st.applyUserInvite(ch.GetUserInvite(), recordId) case ch.GetUserJoin() != nil: - return st.applyUserJoin(ch.GetUserJoin()) + return st.applyUserJoin(ch.GetUserJoin(), recordId) default: return fmt.Errorf("unexpected change type: %v", ch) } } -func (st *AclState) applyUserPermissionChange(ch *aclrecordproto.AclUserPermissionChange) error { - chIdentity := string(ch.Identity) - state, exists := st.userStates[chIdentity] +func (st *AclState) applyUserPermissionChange(ch *aclrecordproto.AclUserPermissionChange, recordId string) error { + chIdentity, err := st.keyStore.PubKeyFromProto(ch.Identity) + if err != nil { + return err + } + state, exists := st.userStates[mapKeyFromPubKey(chIdentity)] if !exists { return ErrNoSuchUser } @@ -293,131 +266,132 @@ func (st *AclState) applyUserPermissionChange(ch *aclrecordproto.AclUserPermissi return nil } -func (st *AclState) applyUserInvite(ch *aclrecordproto.AclUserInvite) error { - st.userInvites[string(ch.AcceptPublicKey)] = ch +func (st *AclState) applyUserInvite(ch *aclrecordproto.AclUserInvite, recordId string) error { + //acceptPubKey, err := st.keyStore.PubKeyFromProto(ch.AcceptPublicKey) + //if err != nil { + // return nil + //} + //st.userInvites[string(ch.AcceptPublicKey)] = ch return nil } -func (st *AclState) applyUserJoin(ch *aclrecordproto.AclUserJoin) error { - invite, exists := st.userInvites[string(ch.AcceptPubKey)] - if !exists { - return fmt.Errorf("no such invite with such public key %s", keys.EncodeBytesToString(ch.AcceptPubKey)) - } - chIdentity := string(ch.Identity) +func (st *AclState) applyUserJoin(ch *aclrecordproto.AclUserJoin, recordId string) error { + //invite, exists := st.userInvites[string(ch.AcceptPubKey)] + //if !exists { + // // TODO: change key to use same encoding + // return fmt.Errorf("no such invite with such public key %s", keys.EncodeBytesToString(ch.AcceptPubKey)) + //} + //chIdentity := string(ch.Identity) + //if _, exists = st.userStates[chIdentity]; exists { + // return ErrUserAlreadyExists + //} + // + //// validating signature + //signature := ch.GetAcceptSignature() + //verificationKey, err := crypto.UnmarshalEd25519PublicKeyProto(invite.AcceptPublicKey) + //if err != nil { + // return fmt.Errorf("public key verifying invite accepts is given in incorrect format: %v", err) + //} + // + //// TODO: intuitively we need to sign not only the identity but a more complicated payload + //res, err := verificationKey.Verify(ch.Identity, signature) + //if err != nil { + // return fmt.Errorf("verification returned error: %w", err) + //} + //if !res { + // return ErrInvalidSignature + //} + // + //// if ourselves -> we need to decrypt the read keys + //if st.identity == chIdentity { + // for _, key := range ch.EncryptedReadKeys { + // key, err := st.decryptReadKey(key) + // if err != nil { + // return ErrFailedToDecrypt + // } + // + // st.userReadKeys[recordId] = key + // } + //} + // + //// adding user to the list + //userState := &aclrecordproto.AclUserState{ + // Identity: ch.Identity, + // Permissions: invite.Permissions, + //} + //st.userStates[chIdentity] = userState + return nil +} - if _, exists = st.userStates[chIdentity]; exists { - return ErrUserAlreadyExists - } +func (st *AclState) applyUserAdd(ch *aclrecordproto.AclUserAdd, recordId string) error { + //chIdentity := string(ch.Identity) + //if _, exists := st.userStates[chIdentity]; exists { + // return ErrUserAlreadyExists + //} + // + //st.userStates[chIdentity] = &aclrecordproto.AclUserState{ + // Identity: ch.Identity, + // EncryptionKey: ch.EncryptionKey, + // Permissions: ch.Permissions, + //} + // + //if chIdentity == st.identity { + // for _, key := range ch.EncryptedReadKeys { + // key, hash, err := st.decryptReadKey(key) + // if err != nil { + // return ErrFailedToDecrypt + // } + // + // st.userReadKeys[hash] = key + // } + //} - // validating signature - signature := ch.GetAcceptSignature() - verificationKey, err := crypto.NewSigningEd25519PubKeyFromBytes(invite.AcceptPublicKey) + return nil +} + +func (st *AclState) applyUserRemove(ch *aclrecordproto.AclUserRemove, recordId string) error { + //chIdentity := string(ch.Identity) + //if chIdentity == st.identity { + // return ErrDocumentForbidden + //} + // + //if _, exists := st.userStates[chIdentity]; !exists { + // return ErrNoSuchUser + //} + // + //delete(st.userStates, chIdentity) + // + //for _, replace := range ch.ReadKeyReplaces { + // repIdentity := string(replace.Identity) + // // if this is our identity then we have to decrypt the key + // if repIdentity == st.identity { + // key, hash, err := st.decryptReadKey(replace.EncryptedReadKey) + // if err != nil { + // return ErrFailedToDecrypt + // } + // + // st.userReadKeys[hash] = key + // break + // } + //} + return nil +} + +func (st *AclState) decryptReadKey(msg []byte) (crypto.SymKey, error) { + decrypted, err := st.key.Decrypt(msg) if err != nil { - return fmt.Errorf("public key verifying invite accepts is given in incorrect format: %v", err) - } - - res, err := verificationKey.Verify(ch.Identity, signature) - if err != nil { - return fmt.Errorf("verification returned error: %w", err) - } - if !res { - return ErrInvalidSignature - } - - // if ourselves -> we need to decrypt the read keys - if st.identity == chIdentity { - for _, key := range ch.EncryptedReadKeys { - key, hash, err := st.decryptReadKeyAndHash(key) - if err != nil { - return ErrFailedToDecrypt - } - - st.userReadKeys[hash] = key - } - } - - // adding user to the list - userState := &aclrecordproto.AclUserState{ - Identity: ch.Identity, - EncryptionKey: ch.EncryptionKey, - Permissions: invite.Permissions, - } - st.userStates[chIdentity] = userState - return nil -} - -func (st *AclState) applyUserAdd(ch *aclrecordproto.AclUserAdd) error { - chIdentity := string(ch.Identity) - if _, exists := st.userStates[chIdentity]; exists { - return ErrUserAlreadyExists - } - - st.userStates[chIdentity] = &aclrecordproto.AclUserState{ - Identity: ch.Identity, - EncryptionKey: ch.EncryptionKey, - Permissions: ch.Permissions, - } - - if chIdentity == st.identity { - for _, key := range ch.EncryptedReadKeys { - key, hash, err := st.decryptReadKeyAndHash(key) - if err != nil { - return ErrFailedToDecrypt - } - - st.userReadKeys[hash] = key - } - } - - return nil -} - -func (st *AclState) applyUserRemove(ch *aclrecordproto.AclUserRemove) error { - chIdentity := string(ch.Identity) - if chIdentity == st.identity { - return ErrDocumentForbidden - } - - if _, exists := st.userStates[chIdentity]; !exists { - return ErrNoSuchUser - } - - delete(st.userStates, chIdentity) - - for _, replace := range ch.ReadKeyReplaces { - repIdentity := string(replace.Identity) - // if this is our identity then we have to decrypt the key - if repIdentity == st.identity { - key, hash, err := st.decryptReadKeyAndHash(replace.EncryptedReadKey) - if err != nil { - return ErrFailedToDecrypt - } - - st.userReadKeys[hash] = key - break - } - } - return nil -} - -func (st *AclState) decryptReadKeyAndHash(msg []byte) (*crypto.AESKey, uint64, error) { - decrypted, err := st.encryptionKey.Decrypt(msg) - if err != nil { - return nil, 0, ErrFailedToDecrypt + return nil, ErrFailedToDecrypt } key, err := crypto.UnmarshallAESKey(decrypted) if err != nil { - return nil, 0, ErrFailedToDecrypt + return nil, ErrFailedToDecrypt } - - hasher := fnv.New64() - hasher.Write(decrypted) - return key, hasher.Sum64(), nil + return key, nil } -func (st *AclState) HasPermission(identity []byte, permission aclrecordproto.AclUserPermissions) bool { - state, exists := st.userStates[string(identity)] +func (st *AclState) HasPermission(identity crypto.PubKey, permission aclrecordproto.AclUserPermissions) bool { + state, exists := st.userStates[mapKeyFromPubKey(identity)] if !exists { return false } @@ -430,36 +404,32 @@ func (st *AclState) isUserJoin(data *aclrecordproto.AclData) bool { return data.GetAclContent() != nil && data.GetAclContent()[0].GetUserJoin() != nil } -func (st *AclState) isUserAdd(data *aclrecordproto.AclData, identity []byte) bool { - // if we have a UserAdd, then it should always be the first one applied - userAdd := data.GetAclContent()[0].GetUserAdd() - return data.GetAclContent() != nil && userAdd != nil && bytes.Compare(userAdd.GetIdentity(), identity) == 0 -} +//func (st *AclState) isUserAdd(data *aclrecordproto.AclData, identity []byte) bool { +// // if we have a UserAdd, then it should always be the first one applied +// userAdd := data.GetAclContent()[0].GetUserAdd() +// return data.GetAclContent() != nil && userAdd != nil && bytes.Compare(userAdd.GetIdentity(), identity) == 0 +//} -func (st *AclState) UserStates() map[string]*aclrecordproto.AclUserState { +func (st *AclState) UserStates() map[string]AclUserState { return st.userStates } -func (st *AclState) Invite(acceptPubKey []byte) (invite *aclrecordproto.AclUserInvite, err error) { - invite, exists := st.userInvites[string(acceptPubKey)] - if !exists { - err = ErrNoSuchInvite - return - } - if len(invite.EncryptedReadKeys) != st.totalReadKeys { - err = ErrOldInvite - } - return -} - -func (st *AclState) UserKeys() (encKey encryptionkey.PrivKey, signKey signingkey.PrivKey) { - return st.encryptionKey, st.signingKey -} - -func (st *AclState) Identity() []byte { - return []byte(st.identity) -} +//func (st *AclState) Invite(acceptPubKey []byte) (invite *aclrecordproto.AclUserInvite, err error) { +// invite, exists := st.userInvites[string(acceptPubKey)] +// if !exists { +// err = ErrNoSuchInvite +// return +// } +// if len(invite.EncryptedReadKeys) != st.totalReadKeys { +// err = ErrOldInvite +// } +// return +//} func (st *AclState) LastRecordId() string { return st.lastRecordId } + +func mapKeyFromPubKey(pubKey crypto.PubKey) string { + return string(pubKey.Storage()) +} diff --git a/commonspace/object/acl/list/list.go b/commonspace/object/acl/list/list.go index e8d074a3..3a670bd1 100644 --- a/commonspace/object/acl/list/list.go +++ b/commonspace/object/acl/list/list.go @@ -9,6 +9,7 @@ import ( "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/keychain" + "github.com/anytypeio/any-sync/util/crypto" "sync" ) @@ -56,11 +57,11 @@ type aclList struct { func BuildAclListWithIdentity(acc *accountdata.AccountData, storage liststorage.ListStorage) (AclList, error) { builder := newAclStateBuilderWithIdentity(acc) - return build(storage.Id(), builder, newAclRecordBuilder(storage.Id(), keychain.NewKeychain()), storage) + return build(storage.Id(), builder, newAclRecordBuilder(storage.Id(), crypto.NewKeyStorage()), storage) } func BuildAclList(storage liststorage.ListStorage) (AclList, error) { - return build(storage.Id(), newAclStateBuilder(), newAclRecordBuilder(storage.Id(), keychain.NewKeychain()), storage) + return build(storage.Id(), newAclStateBuilder(), newAclRecordBuilder(storage.Id(), crypto.NewKeyStorage()), storage) } func build(id string, stateBuilder *aclStateBuilder, recBuilder AclRecordBuilder, storage liststorage.ListStorage) (list AclList, err error) { @@ -74,7 +75,7 @@ func build(id string, stateBuilder *aclStateBuilder, recBuilder AclRecordBuilder return } - record, err := recBuilder.ConvertFromRaw(rawRecordWithId) + record, err := recBuilder.FromRaw(rawRecordWithId) if err != nil { return } @@ -86,7 +87,7 @@ func build(id string, stateBuilder *aclStateBuilder, recBuilder AclRecordBuilder return } - record, err = recBuilder.ConvertFromRaw(rawRecordWithId) + record, err = recBuilder.FromRaw(rawRecordWithId) if err != nil { return } @@ -137,7 +138,7 @@ func (a *aclList) AddRawRecord(rawRec *aclrecordproto.RawAclRecordWithId) (added if _, ok := a.indexes[rawRec.Id]; ok { return } - record, err := a.recordBuilder.ConvertFromRaw(rawRec) + record, err := a.recordBuilder.FromRaw(rawRec) if err != nil { return } @@ -156,7 +157,7 @@ func (a *aclList) AddRawRecord(rawRec *aclrecordproto.RawAclRecordWithId) (added } func (a *aclList) IsValidNext(rawRec *aclrecordproto.RawAclRecordWithId) (err error) { - _, err = a.recordBuilder.ConvertFromRaw(rawRec) + _, err = a.recordBuilder.FromRaw(rawRec) if err != nil { return } diff --git a/commonspace/object/acl/list/list_test.go b/commonspace/object/acl/list/list_test.go index a5b7bd5c..b3cd9166 100644 --- a/commonspace/object/acl/list/list_test.go +++ b/commonspace/object/acl/list/list_test.go @@ -25,7 +25,7 @@ func TestAclList_AclState_UserInviteAndJoin(t *testing.T) { assert.Equal(t, aclrecordproto.AclUserPermissions_Admin, aclList.AclState().UserStates()[idA].Permissions) assert.Equal(t, aclrecordproto.AclUserPermissions_Writer, aclList.AclState().UserStates()[idB].Permissions) assert.Equal(t, aclrecordproto.AclUserPermissions_Reader, aclList.AclState().UserStates()[idC].Permissions) - assert.Equal(t, aclList.Head().CurrentReadKeyHash, aclList.AclState().CurrentReadKeyHash()) + assert.Equal(t, aclList.Head().CurrentReadKeyHash, aclList.AclState().CurrentReadKeyId()) var records []*AclRecord aclList.Iterate(func(record *AclRecord) (IsContinue bool) { @@ -36,10 +36,10 @@ func TestAclList_AclState_UserInviteAndJoin(t *testing.T) { // checking permissions at specific records assert.Equal(t, 3, len(records)) - _, err = aclList.AclState().PermissionsAtRecord(records[1].Id, idB) + _, err = aclList.AclState().StateAtRecord(records[1].Id, idB) assert.Error(t, err, "B should have no permissions at record 1") - perm, err := aclList.AclState().PermissionsAtRecord(records[2].Id, idB) + perm, err := aclList.AclState().StateAtRecord(records[2].Id, idB) assert.NoError(t, err, "should have no error with permissions of B in the record 2") assert.Equal(t, UserPermissionPair{ Identity: idB, @@ -63,7 +63,7 @@ func TestAclList_AclState_UserJoinAndRemove(t *testing.T) { // checking final state assert.Equal(t, aclrecordproto.AclUserPermissions_Admin, aclList.AclState().UserStates()[idA].Permissions) assert.Equal(t, aclrecordproto.AclUserPermissions_Reader, aclList.AclState().UserStates()[idC].Permissions) - assert.Equal(t, aclList.Head().CurrentReadKeyHash, aclList.AclState().CurrentReadKeyHash()) + assert.Equal(t, aclList.Head().CurrentReadKeyHash, aclList.AclState().CurrentReadKeyId()) _, exists := aclList.AclState().UserStates()[idB] assert.Equal(t, false, exists) @@ -77,15 +77,15 @@ func TestAclList_AclState_UserJoinAndRemove(t *testing.T) { // checking permissions at specific records assert.Equal(t, 4, len(records)) - assert.NotEqual(t, records[2].CurrentReadKeyHash, aclList.AclState().CurrentReadKeyHash()) + assert.NotEqual(t, records[2].CurrentReadKeyHash, aclList.AclState().CurrentReadKeyId()) - perm, err := aclList.AclState().PermissionsAtRecord(records[2].Id, idB) + perm, err := aclList.AclState().StateAtRecord(records[2].Id, idB) assert.NoError(t, err, "should have no error with permissions of B in the record 2") assert.Equal(t, UserPermissionPair{ Identity: idB, Permission: aclrecordproto.AclUserPermissions_Writer, }, perm) - _, err = aclList.AclState().PermissionsAtRecord(records[3].Id, idB) + _, err = aclList.AclState().StateAtRecord(records[3].Id, idB) assert.Error(t, err, "B should have no permissions at record 3, because user should be removed") } diff --git a/commonspace/object/acl/list/models.go b/commonspace/object/acl/list/models.go new file mode 100644 index 00000000..8c82325e --- /dev/null +++ b/commonspace/object/acl/list/models.go @@ -0,0 +1,22 @@ +package list + +import ( + "github.com/anytypeio/any-sync/commonspace/object/acl/aclrecordproto" + "github.com/anytypeio/any-sync/util/crypto" +) + +type AclRecord struct { + Id string + PrevId string + ReadKeyId string + Timestamp int64 + Data []byte + Identity crypto.PubKey + Model interface{} + Signature []byte +} + +type AclUserState struct { + PubKey crypto.PubKey + Permissions aclrecordproto.AclUserPermissions +} diff --git a/commonspace/object/acl/list/record.go b/commonspace/object/acl/list/record.go deleted file mode 100644 index b6ad5391..00000000 --- a/commonspace/object/acl/list/record.go +++ /dev/null @@ -1,12 +0,0 @@ -package list - -type AclRecord struct { - Id string - PrevId string - CurrentReadKeyHash uint64 - Timestamp int64 - Data []byte - Identity []byte - Model interface{} - Signature []byte -} diff --git a/commonspace/object/tree/exporter/treeexporter.go b/commonspace/object/tree/exporter/treeexporter.go index 3dabd605..fe77fb26 100644 --- a/commonspace/object/tree/exporter/treeexporter.go +++ b/commonspace/object/tree/exporter/treeexporter.go @@ -68,7 +68,7 @@ func (t *treeExporter) ExportUnencrypted(tree objecttree.ReadableObjectTree) (er return false } // that means that change is unencrypted - change.ReadKeyHash = 0 + change.ReadKeyId = 0 change.Data = data err = putStorage(change) return err == nil diff --git a/commonspace/object/tree/objecttree/change.go b/commonspace/object/tree/objecttree/change.go index ff59c991..4f7ff510 100644 --- a/commonspace/object/tree/objecttree/change.go +++ b/commonspace/object/tree/objecttree/change.go @@ -20,7 +20,7 @@ type Change struct { SnapshotId string IsSnapshot bool Timestamp int64 - ReadKeyHash uint64 + ReadKeyId string Identity string Data []byte Model interface{} @@ -38,7 +38,7 @@ func NewChange(id string, ch *treechangeproto.TreeChange, signature []byte) *Cha PreviousIds: ch.TreeHeadIds, AclHeadId: ch.AclHeadId, Timestamp: ch.Timestamp, - ReadKeyHash: ch.CurrentReadKeyHash, + ReadKeyId: ch.ReadKeyId, Id: id, Data: ch.ChangesData, SnapshotId: ch.SnapshotBaseId, diff --git a/commonspace/object/tree/objecttree/changebuilder.go b/commonspace/object/tree/objecttree/changebuilder.go index 396f5e20..599122be 100644 --- a/commonspace/object/tree/objecttree/changebuilder.go +++ b/commonspace/object/tree/objecttree/changebuilder.go @@ -14,15 +14,15 @@ import ( var ErrEmptyChange = errors.New("change payload should not be empty") type BuilderContent struct { - TreeHeadIds []string - AclHeadId string - SnapshotBaseId string - CurrentReadKeyHash uint64 - Identity []byte - IsSnapshot bool - SigningKey signingkey.PrivKey - ReadKey *crypto.AESKey - Content []byte + TreeHeadIds []string + AclHeadId string + SnapshotBaseId string + ReadKeyId string + Identity []byte + IsSnapshot bool + SigningKey signingkey.PrivKey + ReadKey *crypto.AESKey + Content []byte } type InitialContent struct { @@ -161,13 +161,13 @@ func (c *changeBuilder) BuildRoot(payload InitialContent) (ch *Change, rawIdChan func (c *changeBuilder) Build(payload BuilderContent) (ch *Change, rawIdChange *treechangeproto.RawTreeChangeWithId, err error) { change := &treechangeproto.TreeChange{ - TreeHeadIds: payload.TreeHeadIds, - AclHeadId: payload.AclHeadId, - SnapshotBaseId: payload.SnapshotBaseId, - CurrentReadKeyHash: payload.CurrentReadKeyHash, - Timestamp: time.Now().Unix(), - Identity: payload.Identity, - IsSnapshot: payload.IsSnapshot, + TreeHeadIds: payload.TreeHeadIds, + AclHeadId: payload.AclHeadId, + SnapshotBaseId: payload.SnapshotBaseId, + ReadKeyId: payload.ReadKeyId, + Timestamp: time.Now().Unix(), + Identity: payload.Identity, + IsSnapshot: payload.IsSnapshot, } if payload.ReadKey != nil { var encrypted []byte @@ -212,14 +212,14 @@ func (c *changeBuilder) Marshall(ch *Change) (raw *treechangeproto.RawTreeChange return c.rootChange, nil } treeChange := &treechangeproto.TreeChange{ - TreeHeadIds: ch.PreviousIds, - AclHeadId: ch.AclHeadId, - SnapshotBaseId: ch.SnapshotId, - ChangesData: ch.Data, - CurrentReadKeyHash: ch.ReadKeyHash, - Timestamp: ch.Timestamp, - Identity: []byte(ch.Identity), - IsSnapshot: ch.IsSnapshot, + TreeHeadIds: ch.PreviousIds, + AclHeadId: ch.AclHeadId, + SnapshotBaseId: ch.SnapshotId, + ChangesData: ch.Data, + ReadKeyId: ch.ReadKeyId, + Timestamp: ch.Timestamp, + Identity: []byte(ch.Identity), + IsSnapshot: ch.IsSnapshot, } var marshalled []byte marshalled, err = treeChange.Marshal() diff --git a/commonspace/object/tree/objecttree/objecttree.go b/commonspace/object/tree/objecttree/objecttree.go index 5930334e..a75a44e6 100644 --- a/commonspace/object/tree/objecttree/objecttree.go +++ b/commonspace/object/tree/objecttree/objecttree.go @@ -236,22 +236,22 @@ func (ot *objectTree) prepareBuilderContent(content SignableChangeContent) (cnt } if content.IsEncrypted { - readKeyHash = state.CurrentReadKeyHash() + readKeyHash = state.CurrentReadKeyId() readKey, err = state.CurrentReadKey() if err != nil { return } } cnt = BuilderContent{ - TreeHeadIds: ot.tree.Heads(), - AclHeadId: ot.aclList.Head().Id, - SnapshotBaseId: ot.tree.RootId(), - CurrentReadKeyHash: readKeyHash, - Identity: content.Identity, - IsSnapshot: content.IsSnapshot, - SigningKey: content.Key, - ReadKey: readKey, - Content: content.Data, + TreeHeadIds: ot.tree.Heads(), + AclHeadId: ot.aclList.Head().Id, + SnapshotBaseId: ot.tree.RootId(), + ReadKeyId: readKeyHash, + Identity: content.Identity, + IsSnapshot: content.IsSnapshot, + SigningKey: content.Key, + ReadKey: readKey, + Content: content.Data, } return } @@ -488,11 +488,11 @@ func (ot *objectTree) IterateFrom(id string, convert ChangeConvertFunc, iterate } decrypt := func(c *Change) (decrypted []byte, err error) { // the change is not encrypted - if c.ReadKeyHash == 0 { + if c.ReadKeyId == 0 { decrypted = c.Data return } - readKey, exists := ot.keys[c.ReadKeyHash] + readKey, exists := ot.keys[c.ReadKeyId] if !exists { err = list.ErrNoReadKey return diff --git a/commonspace/object/tree/objecttree/objecttreevalidator.go b/commonspace/object/tree/objecttree/objecttreevalidator.go index 55adc6a7..221b3002 100644 --- a/commonspace/object/tree/objecttree/objecttreevalidator.go +++ b/commonspace/object/tree/objecttree/objecttreevalidator.go @@ -54,7 +54,7 @@ func (v *objectTreeValidator) validateChange(tree *Tree, aclList list.AclList, c state = aclList.AclState() ) // checking if the user could write - perm, err = state.PermissionsAtRecord(c.AclHeadId, c.Identity) + perm, err = state.StateAtRecord(c.AclHeadId, c.Identity) if err != nil { return } diff --git a/util/crypto/ed25519.go b/util/crypto/ed25519.go index 0cdfdb1f..0a0f16cc 100644 --- a/util/crypto/ed25519.go +++ b/util/crypto/ed25519.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "github.com/anytypeio/any-sync/util/crypto/cryptoproto" + "github.com/anytypeio/any-sync/util/strkey" "github.com/gogo/protobuf/proto" "io" "sync" @@ -119,6 +120,11 @@ func (k *Ed25519PrivKey) Decrypt(msg []byte) ([]byte, error) { return DecryptX25519(k.privCurve, k.pubCurve, msg) } +func (k *Ed25519PubKey) String() string { + res, _ := strkey.Encode(strkey.AccountAddressVersionByte, k.pubKey) + return res +} + // Raw public key bytes. func (k *Ed25519PubKey) Raw() ([]byte, error) { return k.pubKey, nil @@ -134,6 +140,11 @@ func (k *Ed25519PubKey) Encrypt(msg []byte) (data []byte, err error) { return } +// Storage returns underlying byte storage +func (k *Ed25519PubKey) Storage() []byte { + return k.pubKey +} + // Equals compares two ed25519 public keys. func (k *Ed25519PubKey) Equals(o Key) bool { edk, ok := o.(*Ed25519PubKey) diff --git a/util/crypto/key.go b/util/crypto/key.go index 21f08142..93642ad4 100644 --- a/util/crypto/key.go +++ b/util/crypto/key.go @@ -38,6 +38,10 @@ type PubKey interface { Verify(data []byte, sig []byte) (bool, error) // Marshall wraps key in proto encoding and marshalls it Marshall() ([]byte, error) + // Storage returns underlying key storage + Storage() []byte + // String returns string representation + String() string } type SymKey interface { diff --git a/util/crypto/keystorage.go b/util/crypto/keystorage.go new file mode 100644 index 00000000..80b1892d --- /dev/null +++ b/util/crypto/keystorage.go @@ -0,0 +1,9 @@ +package crypto + +type KeyStorage interface { + PubKeyFromProto(protoBytes []byte) (PubKey, error) +} + +func NewKeyStorage() KeyStorage { + return nil +}