From 69b21cd8102b3175639046d5e721b7c07734e936 Mon Sep 17 00:00:00 2001 From: mcrakhman Date: Mon, 26 Sep 2022 12:03:20 +0200 Subject: [PATCH] Fixes to acls --- pkg/acl/aclrecordproto/aclrecord.pb.go | 294 ++++++++---------- pkg/acl/aclrecordproto/protos/aclrecord.proto | 6 +- pkg/acl/common/keychain.go | 9 +- pkg/acl/list/aclreadkeyderive.go | 10 + pkg/acl/list/aclrecordbuilder.go | 95 ++++++ pkg/acl/list/aclstate.go | 184 ++++++----- pkg/acl/list/aclstatebuilder.go | 29 +- pkg/acl/list/changebuilder.go | 131 -------- pkg/acl/list/list.go | 82 ++--- pkg/acl/list/record.go | 69 +--- util/keys/symmetric/symmetric.go | 7 + 11 files changed, 401 insertions(+), 515 deletions(-) create mode 100644 pkg/acl/list/aclreadkeyderive.go create mode 100644 pkg/acl/list/aclrecordbuilder.go delete mode 100644 pkg/acl/list/changebuilder.go diff --git a/pkg/acl/aclrecordproto/aclrecord.pb.go b/pkg/acl/aclrecordproto/aclrecord.pb.go index 69035b70..158b70f5 100644 --- a/pkg/acl/aclrecordproto/aclrecord.pb.go +++ b/pkg/acl/aclrecordproto/aclrecord.pb.go @@ -231,11 +231,13 @@ func (m *ACLRecord) GetTimestamp() int64 { } type ACLRoot 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"` - SpaceId string `protobuf:"bytes,3,opt,name=spaceId,proto3" json:"spaceId,omitempty"` - EncryptedReadKey []byte `protobuf:"bytes,4,opt,name=encryptedReadKey,proto3" json:"encryptedReadKey,omitempty"` - DerivationScheme string `protobuf:"bytes,5,opt,name=derivationScheme,proto3" json:"derivationScheme,omitempty"` + Identity []byte `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` + EncryptionKey []byte `protobuf:"bytes,2,opt,name=encryptionKey,proto3" json:"encryptionKey,omitempty"` + SpaceId string `protobuf:"bytes,3,opt,name=spaceId,proto3" json:"spaceId,omitempty"` + EncryptedReadKey []byte `protobuf:"bytes,4,opt,name=encryptedReadKey,proto3" json:"encryptedReadKey,omitempty"` + DerivationScheme string `protobuf:"bytes,5,opt,name=derivationScheme,proto3" json:"derivationScheme,omitempty"` + CurrentReadKeyHash uint64 `protobuf:"varint,6,opt,name=currentReadKeyHash,proto3" json:"currentReadKeyHash,omitempty"` + Timestamp int64 `protobuf:"varint,7,opt,name=timestamp,proto3" json:"timestamp,omitempty"` } func (m *ACLRoot) Reset() { *m = ACLRoot{} } @@ -306,6 +308,20 @@ 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 + } + return 0 +} + type ACLContentValue struct { // Types that are valid to be assigned to Value: // *ACLContentValue_UserAdd @@ -535,11 +551,9 @@ func (m *ACLState) GetInvites() map[string]*ACLUserInvite { } type ACLUserState 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"` - EncryptedReadKeys [][]byte `protobuf:"bytes,3,rep,name=encryptedReadKeys,proto3" json:"encryptedReadKeys,omitempty"` - Permissions ACLUserPermissions `protobuf:"varint,4,opt,name=permissions,proto3,enum=aclrecord.ACLUserPermissions" json:"permissions,omitempty"` - IsConfirmed bool `protobuf:"varint,5,opt,name=isConfirmed,proto3" json:"isConfirmed,omitempty"` + Identity []byte `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"` + EncryptionKey []byte `protobuf:"bytes,2,opt,name=encryptionKey,proto3" json:"encryptionKey,omitempty"` + Permissions ACLUserPermissions `protobuf:"varint,3,opt,name=permissions,proto3,enum=aclrecord.ACLUserPermissions" json:"permissions,omitempty"` } func (m *ACLUserState) Reset() { *m = ACLUserState{} } @@ -589,13 +603,6 @@ func (m *ACLUserState) GetEncryptionKey() []byte { return nil } -func (m *ACLUserState) GetEncryptedReadKeys() [][]byte { - if m != nil { - return m.EncryptedReadKeys - } - return nil -} - func (m *ACLUserState) GetPermissions() ACLUserPermissions { if m != nil { return m.Permissions @@ -603,13 +610,6 @@ func (m *ACLUserState) GetPermissions() ACLUserPermissions { return ACLUserPermissions_Admin } -func (m *ACLUserState) GetIsConfirmed() bool { - if m != nil { - return m.IsConfirmed - } - return false -} - type ACLUserAdd 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"` @@ -1018,61 +1018,61 @@ func init() { } var fileDescriptor_14abe0d1b4206d54 = []byte{ - // 862 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x56, 0xcd, 0x6e, 0x23, 0x45, - 0x10, 0x76, 0x8f, 0x9d, 0x38, 0x53, 0xe3, 0xdd, 0x78, 0x5b, 0x90, 0x1d, 0x45, 0x8b, 0x65, 0x8d, - 0x38, 0x58, 0x2b, 0xf0, 0x82, 0x41, 0x5a, 0x94, 0x03, 0xc8, 0x6b, 0x76, 0x65, 0x93, 0x1c, 0x56, - 0x1d, 0x60, 0x11, 0xb7, 0xde, 0x99, 0x26, 0x69, 0xad, 0x3d, 0x33, 0xea, 0x6e, 0x1b, 0xf9, 0xc8, - 0x1b, 0xf0, 0x0a, 0x3c, 0x08, 0x27, 0x2e, 0x1c, 0x73, 0x41, 0xe2, 0x08, 0xc9, 0x0b, 0x70, 0xe7, - 0x82, 0xba, 0xe7, 0xdf, 0xe3, 0x58, 0x42, 0x8a, 0x90, 0x38, 0x24, 0x9e, 0xaa, 0xfa, 0xaa, 0xfc, - 0xd5, 0xd7, 0x35, 0xd5, 0x86, 0xf7, 0xe3, 0x37, 0x17, 0x4f, 0xa8, 0x3f, 0xd7, 0x7f, 0x82, 0xf9, - 0x91, 0x08, 0x62, 0x11, 0xa9, 0xe8, 0x89, 0xf9, 0x2f, 0x0b, 0xef, 0xd0, 0x38, 0xb0, 0x9d, 0x3b, - 0xbc, 0x17, 0xd0, 0x21, 0xf4, 0xfb, 0xf1, 0xe4, 0x8c, 0x18, 0x1b, 0xbb, 0xd0, 0x8e, 0xe9, 0x7a, - 0x1e, 0xd1, 0xc0, 0x45, 0x7d, 0x34, 0xe8, 0x90, 0xcc, 0xc4, 0x8f, 0xc0, 0x96, 0xfc, 0x22, 0xa4, - 0x6a, 0x29, 0x98, 0x6b, 0x99, 0x58, 0xe1, 0xf0, 0x3e, 0x05, 0x5c, 0xae, 0xf3, 0x8a, 0xab, 0xcb, - 0xd9, 0xae, 0x6a, 0xf7, 0xc1, 0xe2, 0x81, 0x29, 0x63, 0x13, 0x8b, 0x07, 0xde, 0x4f, 0x08, 0xec, - 0x82, 0xc5, 0x11, 0xec, 0xc7, 0x82, 0xad, 0x66, 0x49, 0x9a, 0x4d, 0x52, 0x0b, 0x1f, 0xc3, 0x01, - 0x0f, 0x58, 0xa8, 0xb8, 0x5a, 0xa7, 0x14, 0x72, 0x1b, 0x63, 0x68, 0x05, 0x54, 0x51, 0xb7, 0x69, - 0xfc, 0xe6, 0x19, 0x0f, 0x01, 0xfb, 0x4b, 0x21, 0x58, 0xa8, 0x08, 0xa3, 0xc1, 0x29, 0x5b, 0x4f, - 0xa9, 0xbc, 0x74, 0x5b, 0x7d, 0x34, 0x68, 0x91, 0x2d, 0x11, 0xdd, 0xa3, 0xe2, 0x0b, 0x26, 0x15, - 0x5d, 0xc4, 0xee, 0x5e, 0x1f, 0x0d, 0x9a, 0xa4, 0x70, 0x78, 0x3f, 0x23, 0x68, 0x6b, 0x8e, 0x51, - 0xa4, 0x2a, 0x4c, 0xd0, 0x06, 0x93, 0x77, 0xe1, 0x1e, 0x0b, 0x7d, 0xb1, 0x8e, 0x15, 0x8f, 0xc2, - 0x53, 0x96, 0x51, 0xad, 0x3a, 0xb5, 0x36, 0x32, 0xa6, 0x3e, 0x9b, 0x05, 0x86, 0xb2, 0x4d, 0x32, - 0x13, 0x3f, 0x86, 0x6e, 0x0a, 0x65, 0x41, 0xca, 0xce, 0x70, 0xee, 0x90, 0x9a, 0x5f, 0x63, 0x03, - 0x26, 0xf8, 0x8a, 0xea, 0xb2, 0xe7, 0xfe, 0x25, 0x5b, 0x30, 0x43, 0xdc, 0x26, 0x35, 0xbf, 0xf7, - 0x9b, 0x05, 0x87, 0xe3, 0xc9, 0xd9, 0x24, 0x0a, 0x15, 0x0b, 0xd5, 0xd7, 0x74, 0xbe, 0x64, 0xf8, - 0x43, 0x68, 0x2f, 0x25, 0x13, 0xe3, 0x20, 0x91, 0xda, 0x19, 0xbd, 0x3d, 0x2c, 0xa6, 0x65, 0x3c, - 0x39, 0xfb, 0x2a, 0x09, 0x4e, 0x1b, 0x24, 0xc3, 0xe1, 0x13, 0x00, 0xfd, 0x48, 0xd8, 0x22, 0x5a, - 0x25, 0x93, 0xe0, 0x8c, 0xdc, 0x7a, 0x56, 0x12, 0x9f, 0x36, 0x48, 0x09, 0x8d, 0xbf, 0x81, 0xb7, - 0xb4, 0xf5, 0x92, 0x89, 0x05, 0x97, 0x92, 0x47, 0xe1, 0xe4, 0x92, 0x86, 0x17, 0xcc, 0x28, 0xe0, - 0x8c, 0xbc, 0x7a, 0x95, 0x4d, 0xe4, 0xb4, 0x41, 0xb6, 0x56, 0xc8, 0x58, 0xcd, 0xc2, 0x15, 0x57, - 0xcc, 0xc8, 0xb5, 0x95, 0x55, 0x12, 0xcf, 0x58, 0x25, 0x16, 0xfe, 0x18, 0x0e, 0xb4, 0xf5, 0x45, - 0xc4, 0x43, 0x23, 0x9e, 0x33, 0x3a, 0xaa, 0x67, 0xea, 0xe8, 0xb4, 0x41, 0x72, 0xe4, 0xb3, 0x36, - 0xec, 0xad, 0xb4, 0x86, 0xde, 0x73, 0x33, 0x16, 0x9f, 0xeb, 0x81, 0x3b, 0x01, 0xa0, 0xfe, 0x3c, - 0x55, 0xd8, 0x45, 0xfd, 0xe6, 0xc0, 0x19, 0x1d, 0x57, 0x6b, 0x95, 0xe5, 0x27, 0x25, 0xb4, 0xf7, - 0x37, 0x82, 0x83, 0xf1, 0xe4, 0xec, 0x5c, 0x51, 0xc5, 0xf4, 0x0c, 0x89, 0x62, 0x30, 0x99, 0x34, - 0xb5, 0x5a, 0xa4, 0xea, 0xc4, 0x4f, 0x93, 0xa6, 0x4d, 0x8a, 0x74, 0x2d, 0xf3, 0x75, 0x0f, 0xeb, - 0xd4, 0x4d, 0x9c, 0x94, 0xa0, 0xf8, 0x04, 0xda, 0xdc, 0xf4, 0x2e, 0xdd, 0xa6, 0xc9, 0xea, 0x57, - 0xb3, 0x0c, 0x6c, 0x98, 0xc8, 0x23, 0x9f, 0x87, 0x4a, 0xac, 0x49, 0x96, 0x70, 0xfc, 0x25, 0x74, - 0xca, 0x01, 0xdc, 0x85, 0xe6, 0x1b, 0xb6, 0x4e, 0xdf, 0x54, 0xfd, 0x88, 0x87, 0xa9, 0x32, 0xb7, - 0x0f, 0x47, 0x52, 0x80, 0x24, 0xb0, 0x13, 0xeb, 0x13, 0xe4, 0xfd, 0x89, 0xa0, 0x53, 0xa6, 0x7b, - 0x07, 0x6f, 0xd8, 0x7b, 0xf0, 0x60, 0xf3, 0x7d, 0x49, 0xda, 0xed, 0x90, 0x7a, 0x00, 0x7f, 0x06, - 0x4e, 0x9c, 0x0f, 0x95, 0x34, 0x13, 0x74, 0x7f, 0xf4, 0xce, 0xae, 0x89, 0x94, 0xa4, 0x9c, 0x81, - 0xfb, 0xe0, 0x70, 0x39, 0x89, 0xc2, 0xef, 0xb8, 0x58, 0xb0, 0xc0, 0x0c, 0xd2, 0x01, 0x29, 0xbb, - 0xf4, 0x02, 0x81, 0xe2, 0x9d, 0xfa, 0xdf, 0x75, 0xe8, 0xfd, 0x85, 0xe0, 0x5e, 0xe5, 0x00, 0xf1, - 0x00, 0x0e, 0xa9, 0xef, 0xb3, 0x58, 0xbd, 0x5c, 0xbe, 0x9e, 0x73, 0xff, 0x94, 0x65, 0x9d, 0x6c, - 0xba, 0x4b, 0x4b, 0xad, 0x80, 0x5a, 0x95, 0xa5, 0x56, 0x60, 0xff, 0xe3, 0x83, 0xd3, 0xe7, 0x60, - 0xda, 0x99, 0x05, 0xe9, 0xee, 0xcc, 0x6d, 0xef, 0x17, 0x04, 0x4e, 0x69, 0x01, 0xdc, 0xc1, 0x99, - 0xe5, 0x92, 0x9d, 0xe7, 0xb7, 0x69, 0xb3, 0x2c, 0x59, 0xee, 0xae, 0xf0, 0x6a, 0x55, 0x79, 0x6d, - 0x97, 0x68, 0xef, 0x16, 0x89, 0x3c, 0x99, 0x9f, 0x5b, 0xba, 0x87, 0x77, 0xb5, 0xf1, 0x02, 0x0e, - 0xd3, 0x2d, 0x43, 0x58, 0x3c, 0xa7, 0x7e, 0xbe, 0x23, 0x1e, 0x55, 0x35, 0x25, 0x15, 0x10, 0xd9, - 0x4c, 0xf2, 0x7e, 0x40, 0xf0, 0xa0, 0x06, 0xbb, 0x03, 0x01, 0xb7, 0x5d, 0x8f, 0xcd, 0xed, 0xd7, - 0xa3, 0xb7, 0x82, 0x87, 0xb7, 0x5c, 0x24, 0x3b, 0x89, 0x6c, 0x8c, 0x94, 0xf5, 0x6f, 0x47, 0xea, - 0xf1, 0x53, 0xc0, 0x75, 0x08, 0xb6, 0x61, 0x6f, 0x1c, 0x2c, 0x78, 0xd8, 0x6d, 0x60, 0x80, 0xfd, - 0x57, 0x82, 0x2b, 0x26, 0xba, 0x48, 0x3f, 0x6b, 0xbe, 0x4c, 0x74, 0xad, 0x67, 0x1f, 0xfc, 0x7a, - 0xdd, 0x43, 0x57, 0xd7, 0x3d, 0xf4, 0xc7, 0x75, 0x0f, 0xfd, 0x78, 0xd3, 0x6b, 0x5c, 0xdd, 0xf4, - 0x1a, 0xbf, 0xdf, 0xf4, 0x1a, 0xdf, 0x1e, 0x6d, 0xff, 0x8d, 0xf7, 0x7a, 0xdf, 0x7c, 0x7c, 0xf4, - 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x93, 0x89, 0xed, 0xeb, 0x04, 0x0a, 0x00, 0x00, + // 859 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x4f, 0x6f, 0x1b, 0x45, + 0x14, 0xdf, 0x59, 0x3b, 0x71, 0xf6, 0xd9, 0x6d, 0xdc, 0x11, 0xa4, 0xab, 0xa8, 0x58, 0xd6, 0x8a, + 0x83, 0x55, 0x81, 0x0b, 0x06, 0xa9, 0x28, 0x07, 0x90, 0x6b, 0x5a, 0xd9, 0x24, 0x87, 0x6a, 0x02, + 0x14, 0x71, 0x9b, 0xee, 0x8e, 0x92, 0x51, 0xed, 0xdd, 0xd5, 0xec, 0xd8, 0xc8, 0x47, 0xce, 0x5c, + 0xe0, 0x23, 0xf0, 0x41, 0x38, 0x71, 0xe1, 0xd8, 0x0b, 0x12, 0x47, 0x94, 0x7c, 0x01, 0xee, 0x5c, + 0xd0, 0xcc, 0xfe, 0xdf, 0xb5, 0x2d, 0x2a, 0x59, 0x3d, 0x24, 0xde, 0xf7, 0xde, 0xef, 0x3d, 0xff, + 0xe6, 0xf7, 0xde, 0xbc, 0x35, 0x7c, 0x18, 0xbe, 0xba, 0x7a, 0x44, 0xdd, 0xb9, 0xfa, 0x13, 0xcc, + 0x0d, 0x84, 0x17, 0x8a, 0x40, 0x06, 0x8f, 0xf4, 0xff, 0x28, 0xf7, 0x0e, 0xb5, 0x03, 0x5b, 0x99, + 0xc3, 0x79, 0x06, 0x1d, 0x42, 0x7f, 0x18, 0x4f, 0x2e, 0x88, 0xb6, 0xb1, 0x0d, 0xad, 0x90, 0xae, + 0xe7, 0x01, 0xf5, 0x6c, 0xd4, 0x47, 0x83, 0x0e, 0x49, 0x4d, 0xfc, 0x00, 0xac, 0x88, 0x5f, 0xf9, + 0x54, 0x2e, 0x05, 0xb3, 0x4d, 0x1d, 0xcb, 0x1d, 0xce, 0xe7, 0x80, 0x8b, 0x75, 0x5e, 0x70, 0x79, + 0x3d, 0xdb, 0x55, 0xed, 0x2e, 0x98, 0xdc, 0xd3, 0x65, 0x2c, 0x62, 0x72, 0xcf, 0xf9, 0x15, 0x81, + 0x95, 0xb3, 0x38, 0x81, 0xc3, 0x50, 0xb0, 0xd5, 0x2c, 0x4e, 0xb3, 0x48, 0x62, 0xe1, 0x53, 0x38, + 0xe2, 0x1e, 0xf3, 0x25, 0x97, 0xeb, 0x84, 0x42, 0x66, 0x63, 0x0c, 0x4d, 0x8f, 0x4a, 0x6a, 0x37, + 0xb4, 0x5f, 0x3f, 0xe3, 0x21, 0x60, 0x77, 0x29, 0x04, 0xf3, 0x25, 0x61, 0xd4, 0x3b, 0x67, 0xeb, + 0x29, 0x8d, 0xae, 0xed, 0x66, 0x1f, 0x0d, 0x9a, 0x64, 0x43, 0x44, 0x9d, 0x51, 0xf2, 0x05, 0x8b, + 0x24, 0x5d, 0x84, 0xf6, 0x41, 0x1f, 0x0d, 0x1a, 0x24, 0x77, 0x38, 0x3f, 0x99, 0xd0, 0x52, 0x1c, + 0x83, 0x40, 0x96, 0x98, 0xa0, 0x0a, 0x93, 0xf7, 0xe1, 0x0e, 0xf3, 0x5d, 0xb1, 0x0e, 0x25, 0x0f, + 0xfc, 0x73, 0x96, 0x52, 0x2d, 0x3b, 0x95, 0x36, 0x51, 0x48, 0x5d, 0x36, 0xf3, 0x34, 0x65, 0x8b, + 0xa4, 0x26, 0x7e, 0x08, 0xdd, 0x04, 0xca, 0xbc, 0x84, 0x9d, 0xe6, 0xdc, 0x21, 0x35, 0xbf, 0xc2, + 0x7a, 0x4c, 0xf0, 0x15, 0x55, 0x65, 0x2f, 0xdd, 0x6b, 0xb6, 0x60, 0x9a, 0xb8, 0x45, 0x6a, 0xfe, + 0x2d, 0x6a, 0x1c, 0xfe, 0x3f, 0x35, 0x5a, 0x55, 0x35, 0xfe, 0x34, 0xe1, 0x78, 0x3c, 0xb9, 0x98, + 0x04, 0xbe, 0x64, 0xbe, 0xfc, 0x96, 0xce, 0x97, 0x0c, 0x7f, 0x0c, 0xad, 0x65, 0xc4, 0xc4, 0xd8, + 0x8b, 0x1b, 0xd7, 0x1e, 0xbd, 0x3b, 0xcc, 0x67, 0x6f, 0x3c, 0xb9, 0xf8, 0x26, 0x0e, 0x4e, 0x0d, + 0x92, 0xe2, 0xf0, 0x19, 0x80, 0x7a, 0x24, 0x6c, 0x11, 0xac, 0xe2, 0xb9, 0x6a, 0x8f, 0xec, 0x7a, + 0x56, 0x1c, 0x9f, 0x1a, 0xa4, 0x80, 0xc6, 0xdf, 0xc1, 0x3b, 0xca, 0x7a, 0xce, 0xc4, 0x82, 0x47, + 0x11, 0x0f, 0xfc, 0xc9, 0x35, 0xf5, 0xaf, 0x98, 0xd6, 0xb3, 0x3d, 0x72, 0xea, 0x55, 0xaa, 0xc8, + 0xa9, 0x41, 0x36, 0x56, 0x48, 0x59, 0xcd, 0xfc, 0x15, 0x97, 0x4c, 0x8b, 0xbf, 0x91, 0x55, 0x1c, + 0x4f, 0x59, 0xc5, 0x16, 0xfe, 0x14, 0x8e, 0x94, 0xf5, 0x55, 0xc0, 0x7d, 0xdd, 0x8a, 0xf6, 0xe8, + 0xa4, 0x9e, 0xa9, 0xa2, 0x53, 0x83, 0x64, 0xc8, 0x27, 0x2d, 0x38, 0x58, 0x29, 0x0d, 0x9d, 0xa7, + 0x7a, 0xc8, 0xbe, 0x54, 0xe3, 0x7b, 0x06, 0x40, 0xdd, 0x79, 0xa2, 0xb0, 0x8d, 0xfa, 0x8d, 0x41, + 0x7b, 0x74, 0x5a, 0xae, 0x55, 0x94, 0x9f, 0x14, 0xd0, 0xce, 0xbf, 0x08, 0x8e, 0xc6, 0x93, 0x8b, + 0x4b, 0x49, 0x25, 0x53, 0x13, 0x29, 0xf2, 0xc6, 0xb2, 0x48, 0xd7, 0x6a, 0x92, 0xb2, 0x13, 0x3f, + 0x8e, 0x0f, 0xad, 0x53, 0x22, 0xdb, 0xd4, 0x5f, 0x77, 0xbf, 0x4e, 0x5d, 0xc7, 0x49, 0x01, 0x8a, + 0xcf, 0xa0, 0xc5, 0xf5, 0xd9, 0x23, 0xbb, 0xa1, 0xb3, 0xfa, 0xe5, 0x2c, 0x0d, 0x1b, 0xc6, 0xf2, + 0x44, 0x4f, 0x7d, 0x29, 0xd6, 0x24, 0x4d, 0x38, 0xfd, 0x1a, 0x3a, 0xc5, 0x00, 0xee, 0x42, 0xe3, + 0x15, 0x5b, 0x27, 0xf7, 0x5e, 0x3d, 0xe2, 0x61, 0xa2, 0xcc, 0xf6, 0xe1, 0x88, 0x0b, 0x90, 0x18, + 0x76, 0x66, 0x7e, 0x86, 0x9c, 0x5f, 0x10, 0x74, 0x8a, 0x74, 0xf7, 0x70, 0x5f, 0xbf, 0x80, 0x76, + 0x98, 0x8d, 0x49, 0xa4, 0x67, 0xec, 0xee, 0xe8, 0xbd, 0x5d, 0x33, 0x16, 0x91, 0x62, 0x86, 0xf3, + 0x1b, 0x02, 0xc8, 0xef, 0xc0, 0x1e, 0x18, 0x7d, 0x00, 0xf7, 0xaa, 0xfb, 0x20, 0x6e, 0x40, 0x87, + 0xd4, 0x03, 0x55, 0xfe, 0xcd, 0x37, 0xe6, 0xff, 0x0f, 0x82, 0x3b, 0x25, 0xc1, 0xf1, 0x00, 0x8e, + 0xa9, 0xeb, 0xb2, 0x50, 0x3e, 0x5f, 0xbe, 0x9c, 0x73, 0xf7, 0x9c, 0xa5, 0x27, 0xa9, 0xba, 0x0b, + 0x2b, 0x2d, 0x87, 0x9a, 0xa5, 0x95, 0x96, 0x63, 0xdf, 0xee, 0xb1, 0x74, 0x1f, 0xf4, 0x71, 0x66, + 0x5e, 0xb2, 0x39, 0x33, 0xdb, 0xf9, 0x1d, 0x41, 0xbb, 0x70, 0x61, 0xf7, 0xd0, 0xb3, 0x4c, 0xb2, + 0xcb, 0xec, 0x5d, 0xda, 0x28, 0x4a, 0x96, 0xb9, 0x4b, 0xbc, 0x9a, 0x65, 0x5e, 0x9b, 0x25, 0x3a, + 0xd8, 0x22, 0x91, 0x13, 0x65, 0x7d, 0x4b, 0xf6, 0xe6, 0xae, 0x63, 0x3c, 0x83, 0xe3, 0x64, 0x2b, + 0x10, 0x16, 0xce, 0xa9, 0x9b, 0xdd, 0xe9, 0x07, 0x65, 0x4d, 0x49, 0x09, 0x44, 0xaa, 0x49, 0xce, + 0x8f, 0x08, 0xee, 0xd5, 0x60, 0x7b, 0x10, 0x70, 0xd3, 0xcb, 0xb1, 0xb1, 0xf9, 0xe5, 0xe8, 0xac, + 0xe0, 0xfe, 0x96, 0xc5, 0xbf, 0x93, 0x48, 0x65, 0xa4, 0xcc, 0x37, 0x1d, 0xa9, 0x87, 0x8f, 0x01, + 0xd7, 0x21, 0xd8, 0x82, 0x83, 0xb1, 0xb7, 0xe0, 0x7e, 0xd7, 0xc0, 0x00, 0x87, 0x2f, 0x04, 0x97, + 0x4c, 0x74, 0x91, 0x7a, 0x56, 0x7c, 0x99, 0xe8, 0x9a, 0x4f, 0x3e, 0xfa, 0xe3, 0xa6, 0x87, 0x5e, + 0xdf, 0xf4, 0xd0, 0xdf, 0x37, 0x3d, 0xf4, 0xf3, 0x6d, 0xcf, 0x78, 0x7d, 0xdb, 0x33, 0xfe, 0xba, + 0xed, 0x19, 0xdf, 0x9f, 0x6c, 0xfe, 0x85, 0xf7, 0xf2, 0x50, 0x7f, 0x7c, 0xf2, 0x5f, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x0d, 0xd2, 0xee, 0x14, 0x02, 0x0a, 0x00, 0x00, } func (m *RawACLRecord) Marshal() (dAtA []byte, err error) { @@ -1223,6 +1223,16 @@ func (m *ACLRoot) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Timestamp != 0 { + i = encodeVarintAclrecord(dAtA, i, uint64(m.Timestamp)) + i-- + dAtA[i] = 0x38 + } + if m.CurrentReadKeyHash != 0 { + i = encodeVarintAclrecord(dAtA, i, uint64(m.CurrentReadKeyHash)) + i-- + dAtA[i] = 0x30 + } if len(m.DerivationScheme) > 0 { i -= len(m.DerivationScheme) copy(dAtA[i:], m.DerivationScheme) @@ -1536,29 +1546,10 @@ func (m *ACLUserState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.IsConfirmed { - i-- - if m.IsConfirmed { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i-- - dAtA[i] = 0x28 - } if m.Permissions != 0 { i = encodeVarintAclrecord(dAtA, i, uint64(m.Permissions)) i-- - dAtA[i] = 0x20 - } - if len(m.EncryptedReadKeys) > 0 { - for iNdEx := len(m.EncryptedReadKeys) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.EncryptedReadKeys[iNdEx]) - copy(dAtA[i:], m.EncryptedReadKeys[iNdEx]) - i = encodeVarintAclrecord(dAtA, i, uint64(len(m.EncryptedReadKeys[iNdEx]))) - i-- - dAtA[i] = 0x1a - } + dAtA[i] = 0x18 } if len(m.EncryptionKey) > 0 { i -= len(m.EncryptionKey) @@ -1967,6 +1958,12 @@ 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)) + } return n } @@ -2106,18 +2103,9 @@ func (m *ACLUserState) Size() (n int) { if l > 0 { n += 1 + l + sovAclrecord(uint64(l)) } - if len(m.EncryptedReadKeys) > 0 { - for _, b := range m.EncryptedReadKeys { - l = len(b) - n += 1 + l + sovAclrecord(uint64(l)) - } - } if m.Permissions != 0 { n += 1 + sovAclrecord(uint64(m.Permissions)) } - if m.IsConfirmed { - n += 2 - } return n } @@ -2887,6 +2875,44 @@ func (m *ACLRoot) Unmarshal(dAtA []byte) error { } m.DerivationScheme = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 6: + 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 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + } + m.Timestamp = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAclrecord + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Timestamp |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipAclrecord(dAtA[iNdEx:]) @@ -3604,38 +3630,6 @@ func (m *ACLUserState) Unmarshal(dAtA []byte) error { } iNdEx = postIndex case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field EncryptedReadKeys", 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.EncryptedReadKeys = append(m.EncryptedReadKeys, make([]byte, postIndex-iNdEx)) - copy(m.EncryptedReadKeys[len(m.EncryptedReadKeys)-1], dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 4: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field Permissions", wireType) } @@ -3654,26 +3648,6 @@ func (m *ACLUserState) Unmarshal(dAtA []byte) error { break } } - case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field IsConfirmed", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowAclrecord - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.IsConfirmed = bool(v != 0) default: iNdEx = preIndex skippy, err := skipAclrecord(dAtA[iNdEx:]) diff --git a/pkg/acl/aclrecordproto/protos/aclrecord.proto b/pkg/acl/aclrecordproto/protos/aclrecord.proto index 01b5aa6f..4d2a969a 100644 --- a/pkg/acl/aclrecordproto/protos/aclrecord.proto +++ b/pkg/acl/aclrecordproto/protos/aclrecord.proto @@ -26,6 +26,8 @@ message ACLRoot { string spaceId = 3; bytes encryptedReadKey = 4; string derivationScheme = 5; + uint64 currentReadKeyHash = 6; + int64 timestamp = 7; } message ACLContentValue { @@ -51,9 +53,7 @@ message ACLState { message ACLUserState { bytes identity = 1; bytes encryptionKey = 2; - repeated bytes encryptedReadKeys = 3; - ACLUserPermissions permissions = 4; - bool isConfirmed = 5; + ACLUserPermissions permissions = 3; } message ACLUserAdd { diff --git a/pkg/acl/common/keychain.go b/pkg/acl/common/keychain.go index d90965c6..b9fc0fb6 100644 --- a/pkg/acl/common/keychain.go +++ b/pkg/acl/common/keychain.go @@ -1,19 +1,16 @@ package common import ( - "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey" ) type Keychain struct { - decoder keys.Decoder - keys map[string]signingkey.PubKey + keys map[string]signingkey.PubKey } func NewKeychain() *Keychain { return &Keychain{ - decoder: signingkey.NewEDPubKeyDecoder(), - keys: make(map[string]signingkey.PubKey), + keys: make(map[string]signingkey.PubKey), } } @@ -21,7 +18,7 @@ func (k *Keychain) GetOrAdd(identity string) (signingkey.PubKey, error) { if key, exists := k.keys[identity]; exists { return key, nil } - res, err := k.decoder.DecodeFromBytes([]byte(identity)) + res, err := signingkey.NewSigningEd25519PubKeyFromBytes([]byte(identity)) if err != nil { return nil, err } diff --git a/pkg/acl/list/aclreadkeyderive.go b/pkg/acl/list/aclreadkeyderive.go new file mode 100644 index 00000000..c20b2501 --- /dev/null +++ b/pkg/acl/list/aclreadkeyderive.go @@ -0,0 +1,10 @@ +package list + +import "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric" + +func ACLReadKeyDerive(signKey []byte, encKey []byte) (*symmetric.Key, error) { + concBuf := make([]byte, 0, len(signKey)+len(encKey)) + concBuf = append(concBuf, signKey...) + concBuf = append(concBuf, encKey...) + return symmetric.DeriveFromBytes(concBuf) +} diff --git a/pkg/acl/list/aclrecordbuilder.go b/pkg/acl/list/aclrecordbuilder.go new file mode 100644 index 00000000..26c9e08f --- /dev/null +++ b/pkg/acl/list/aclrecordbuilder.go @@ -0,0 +1,95 @@ +package list + +import ( + "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto" + "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/common" + "github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid" + "github.com/gogo/protobuf/proto" +) + +type ACLRecordBuilder interface { + ConvertFromRaw(rawIdRecord *aclrecordproto.RawACLRecordWithId) (rec *ACLRecord, err error) +} + +type aclRecordBuilder struct { + id string + keychain *common.Keychain +} + +func newACLRecordBuilder(id string, keychain *common.Keychain) ACLRecordBuilder { + return &aclRecordBuilder{ + id: id, + keychain: keychain, + } +} + +func (a *aclRecordBuilder) ConvertFromRaw(rawIdRecord *aclrecordproto.RawACLRecordWithId) (rec *ACLRecord, err error) { + rawRec := &aclrecordproto.RawACLRecord{} + 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 + } + + rec = &ACLRecord{ + Id: rawIdRecord.Id, + CurrentReadKeyHash: aclRoot.CurrentReadKeyHash, + Timestamp: aclRoot.Timestamp, + Signature: rawRec.Signature, + Identity: aclRoot.Identity, + Model: aclRoot, + } + } else { + aclRecord := &aclrecordproto.ACLRecord{} + err = proto.Unmarshal(rawRec.Payload, aclRecord) + 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, + } + } + + err = verifyRaw(a.keychain, rawRec, rawIdRecord, rec.Identity) + return +} + +func verifyRaw( + keychain *common.Keychain, + rawRec *aclrecordproto.RawACLRecord, + recWithId *aclrecordproto.RawACLRecordWithId, + identity []byte) (err error) { + identityKey, err := keychain.GetOrAdd(string(identity)) + if err != nil { + return + } + + // verifying signature + res, err := identityKey.Verify(rawRec.Payload, rawRec.Signature) + if err != nil { + return + } + if !res { + err = ErrInvalidSignature + return + } + + // verifying ID + if !cid.VerifyCID(recWithId.Payload, recWithId.Id) { + err = ErrIncorrectCID + } + return +} diff --git a/pkg/acl/list/aclstate.go b/pkg/acl/list/aclstate.go index 27416972..166fff71 100644 --- a/pkg/acl/list/aclstate.go +++ b/pkg/acl/list/aclstate.go @@ -27,6 +27,7 @@ var ErrNoSuchRecord = errors.New("no such record") var ErrInsufficientPermissions = errors.New("insufficient permissions") var ErrNoReadKey = errors.New("acl state doesn't have a read key") var ErrInvalidSignature = errors.New("signature is invalid") +var ErrIncorrectRoot = errors.New("incorrect root") type UserPermissionPair struct { Identity string @@ -34,13 +35,13 @@ type UserPermissionPair struct { } type ACLState struct { + id string currentReadKeyHash uint64 userReadKeys map[uint64]*symmetric.Key userStates map[string]*aclrecordproto.ACLUserState userInvites map[string]*aclrecordproto.ACLUserInvite - - signingPubKeyDecoder keys.Decoder - encryptionKey encryptionkey.PrivKey + encryptionKey encryptionkey.PrivKey + signingKey signingkey.PrivKey identity string permissionsAtRecord map[string][]UserPermissionPair @@ -48,30 +49,30 @@ type ACLState struct { keychain *common.Keychain } -func newACLStateWithIdentity( - identity string, - encryptionKey encryptionkey.PrivKey, - decoder keys.Decoder) *ACLState { - return &ACLState{ - identity: identity, - encryptionKey: encryptionKey, - userReadKeys: make(map[uint64]*symmetric.Key), - userStates: make(map[string]*aclrecordproto.ACLUserState), - userInvites: make(map[string]*aclrecordproto.ACLUserInvite), - signingPubKeyDecoder: decoder, - permissionsAtRecord: make(map[string][]UserPermissionPair), - keychain: common.NewKeychain(), +func newACLStateWithKeys( + signingKey signingkey.PrivKey, + encryptionKey encryptionkey.PrivKey) (*ACLState, error) { + identity, err := signingKey.Raw() + if err != nil { + return nil, err } + return &ACLState{ + identity: string(identity), + signingKey: signingKey, + encryptionKey: encryptionKey, + userReadKeys: make(map[uint64]*symmetric.Key), + userStates: make(map[string]*aclrecordproto.ACLUserState), + userInvites: make(map[string]*aclrecordproto.ACLUserInvite), + permissionsAtRecord: make(map[string][]UserPermissionPair), + }, nil } func newACLState(decoder keys.Decoder) *ACLState { return &ACLState{ - signingPubKeyDecoder: decoder, - userReadKeys: make(map[uint64]*symmetric.Key), - userStates: make(map[string]*aclrecordproto.ACLUserState), - userInvites: make(map[string]*aclrecordproto.ACLUserInvite), - permissionsAtRecord: make(map[string][]UserPermissionPair), - keychain: common.NewKeychain(), + userReadKeys: make(map[uint64]*symmetric.Key), + userStates: make(map[string]*aclrecordproto.ACLUserState), + userInvites: make(map[string]*aclrecordproto.ACLUserInvite), + permissionsAtRecord: make(map[string][]UserPermissionPair), } } @@ -106,40 +107,27 @@ func (st *ACLState) PermissionsAtRecord(id string, identity string) (UserPermiss return UserPermissionPair{}, ErrNoSuchUser } -func (st *ACLState) applyRecord(record *aclrecordproto.ACLRecord) (err error) { +func (st *ACLState) applyRecord(record *ACLRecord) (err error) { + if record.Id == st.id { + root, ok := record.Model.(*aclrecordproto.ACLRoot) + if !ok { + return ErrIncorrectRoot + } + return st.applyRoot(root) + } aclData := &aclrecordproto.ACLData{} - err = proto.Unmarshal(record.Data, aclData) - if err != nil { - return - } - - err = st.applyChangeData(aclData, record.CurrentReadKeyHash, record.Identity) - if err != nil { - return - } - - st.currentReadKeyHash = record.CurrentReadKeyHash - return -} - -func (st *ACLState) applyChangeAndUpdate(recordWrapper *ACLRecord) (err error) { - var ( - change = recordWrapper.Content - aclData = &aclrecordproto.ACLData{} - ) - - if recordWrapper.Model != nil { - aclData = recordWrapper.Model.(*aclrecordproto.ACLData) + if record.Model != nil { + aclData = record.Model.(*aclrecordproto.ACLData) } else { - err = proto.Unmarshal(change.Data, aclData) + err = proto.Unmarshal(record.Data, aclData) if err != nil { return } - recordWrapper.Model = aclData + record.Model = aclData } - err = st.applyChangeData(aclData, recordWrapper.Content.CurrentReadKeyHash, recordWrapper.Content.Identity) + err = st.applyChangeData(aclData, record.CurrentReadKeyHash, record.Identity) if err != nil { return } @@ -154,10 +142,61 @@ func (st *ACLState) applyChangeAndUpdate(recordWrapper *ACLRecord) (err error) { permissions = append(permissions, permission) } - st.permissionsAtRecord[recordWrapper.Id] = permissions + st.permissionsAtRecord[record.Id] = permissions return nil } +func (st *ACLState) applyRoot(root *aclrecordproto.ACLRoot) (err error) { + if st.signingKey != nil && st.encryptionKey != nil { + err = st.saveReadKeyFromRoot(root) + if err != nil { + return + } + } + + // adding user to the list + userState := &aclrecordproto.ACLUserState{ + Identity: root.Identity, + EncryptionKey: root.EncryptionKey, + Permissions: aclrecordproto.ACLUserPermissions_Admin, + } + st.userStates[string(root.Identity)] = userState + return +} + +func (st *ACLState) saveReadKeyFromRoot(root *aclrecordproto.ACLRoot) (err error) { + var readKey *symmetric.Key + if len(root.GetDerivationScheme()) != 0 { + var encPubKey []byte + encPubKey, err = st.encryptionKey.GetPublic().Raw() + if err != nil { + return + } + + readKey, err = ACLReadKeyDerive([]byte(st.identity), encPubKey) + if err != nil { + return + } + } else { + readKey, _, err = st.decryptReadKeyAndHash(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.currentReadKeyHash = root.CurrentReadKeyHash + st.userReadKeys[root.CurrentReadKeyHash] = readKey + return +} + func (st *ACLState) applyChangeData(changeData *aclrecordproto.ACLData, hash uint64, identity []byte) (err error) { defer func() { if err != nil { @@ -166,11 +205,8 @@ func (st *ACLState) applyChangeData(changeData *aclrecordproto.ACLData, hash uin st.currentReadKeyHash = hash }() - // we can't check this for the user which is joining, because it will not be in our list - // the same is for the first change to be added - skipIdentityCheck := st.isUserJoin(changeData) || (st.currentReadKeyHash == 0 && st.isUserAdd(changeData, identity)) - if !skipIdentityCheck { - // we check signature when we add this to the Tree, so no need to do it here + if !st.isUserJoin(changeData) { + // we check signature when we add this to the List, so no need to do it here if _, exists := st.userStates[string(identity)]; !exists { err = ErrNoSuchUser return @@ -204,8 +240,6 @@ func (st *ACLState) applyChangeContent(ch *aclrecordproto.ACLContentValue) error return st.applyUserInvite(ch.GetUserInvite()) case ch.GetUserJoin() != nil: return st.applyUserJoin(ch.GetUserJoin()) - case ch.GetUserConfirm() != nil: - return st.applyUserConfirm(ch.GetUserConfirm()) default: return fmt.Errorf("unexpected change type: %v", ch) } @@ -228,9 +262,9 @@ func (st *ACLState) applyUserInvite(ch *aclrecordproto.ACLUserInvite) error { } func (st *ACLState) applyUserJoin(ch *aclrecordproto.ACLUserJoin) error { - invite, exists := st.userInvites[ch.UserInviteId] + invite, exists := st.userInvites[ch.InviteId] if !exists { - return fmt.Errorf("no such invite with id %s", ch.UserInviteId) + return fmt.Errorf("no such invite with id %s", ch.InviteId) } chIdentity := string(ch.Identity) @@ -240,7 +274,7 @@ func (st *ACLState) applyUserJoin(ch *aclrecordproto.ACLUserJoin) error { // validating signature signature := ch.GetAcceptSignature() - verificationKey, err := st.signingPubKeyDecoder.DecodeFromBytes(invite.AcceptPublicKey) + verificationKey, err := signingkey.NewSigningEd25519PubKeyFromBytes(invite.AcceptPublicKey) if err != nil { return fmt.Errorf("public key verifying invite accepts is given in incorrect format: %v", err) } @@ -267,11 +301,9 @@ func (st *ACLState) applyUserJoin(ch *aclrecordproto.ACLUserJoin) error { // adding user to the list userState := &aclrecordproto.ACLUserState{ - Identity: ch.Identity, - EncryptionKey: ch.EncryptionKey, - EncryptedReadKeys: ch.EncryptedReadKeys, - Permissions: invite.Permissions, - IsConfirmed: true, + Identity: ch.Identity, + EncryptionKey: ch.EncryptionKey, + Permissions: invite.Permissions, } st.userStates[chIdentity] = userState return nil @@ -284,10 +316,9 @@ func (st *ACLState) applyUserAdd(ch *aclrecordproto.ACLUserAdd) error { } st.userStates[chIdentity] = &aclrecordproto.ACLUserState{ - Identity: ch.Identity, - EncryptionKey: ch.EncryptionKey, - Permissions: ch.Permissions, - EncryptedReadKeys: ch.EncryptedReadKeys, + Identity: ch.Identity, + EncryptionKey: ch.EncryptionKey, + Permissions: ch.Permissions, } if chIdentity == st.identity { @@ -318,12 +349,6 @@ func (st *ACLState) applyUserRemove(ch *aclrecordproto.ACLUserRemove) error { for _, replace := range ch.ReadKeyReplaces { repIdentity := string(replace.Identity) - userState, exists := st.userStates[repIdentity] - if !exists { - continue - } - - userState.EncryptedReadKeys = append(userState.EncryptedReadKeys, replace.EncryptedReadKey) // if this is our identity then we have to decrypt the key if repIdentity == st.identity { key, hash, err := st.decryptReadKeyAndHash(replace.EncryptedReadKey) @@ -338,17 +363,6 @@ func (st *ACLState) applyUserRemove(ch *aclrecordproto.ACLUserRemove) error { return nil } -func (st *ACLState) applyUserConfirm(ch *aclrecordproto.ACLUserConfirm) error { - chIdentity := string(ch.Identity) - state, exists := st.userStates[chIdentity] - if !exists { - return ErrNoSuchUser - } - - state.IsConfirmed = true - return nil -} - func (st *ACLState) decryptReadKeyAndHash(msg []byte) (*symmetric.Key, uint64, error) { decrypted, err := st.encryptionKey.Decrypt(msg) if err != nil { diff --git a/pkg/acl/list/aclstatebuilder.go b/pkg/acl/list/aclstatebuilder.go index da79141b..2d7693fb 100644 --- a/pkg/acl/list/aclstatebuilder.go +++ b/pkg/acl/list/aclstatebuilder.go @@ -4,19 +4,20 @@ import ( "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/encryptionkey" + "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey" ) type aclStateBuilder struct { - identity string - key encryptionkey.PrivKey - decoder keys.Decoder + signPrivKey signingkey.PrivKey + encPrivKey encryptionkey.PrivKey + decoder keys.Decoder } func newACLStateBuilderWithIdentity(decoder keys.Decoder, accountData *account.AccountData) *aclStateBuilder { return &aclStateBuilder{ - decoder: decoder, - identity: string(accountData.Identity), - key: accountData.EncKey, + decoder: decoder, + signPrivKey: accountData.SignKey, + encPrivKey: accountData.EncKey, } } @@ -26,19 +27,17 @@ func newACLStateBuilder(decoder keys.Decoder) *aclStateBuilder { } } -func (sb *aclStateBuilder) Build(records []*ACLRecord) (*ACLState, error) { - var ( - err error - state *ACLState - ) - - if sb.key != nil { - state = newACLStateWithIdentity(sb.identity, sb.key, sb.decoder) +func (sb *aclStateBuilder) Build(records []*ACLRecord) (state *ACLState, err error) { + if sb.encPrivKey != nil && sb.signPrivKey != nil { + state, err = newACLStateWithKeys(sb.signPrivKey, sb.encPrivKey) + if err != nil { + return + } } else { state = newACLState(sb.decoder) } for _, rec := range records { - err = state.applyChangeAndUpdate(rec) + err = state.applyRecord(rec) if err != nil { return nil, err } diff --git a/pkg/acl/list/changebuilder.go b/pkg/acl/list/changebuilder.go deleted file mode 100644 index f56e5259..00000000 --- a/pkg/acl/list/changebuilder.go +++ /dev/null @@ -1,131 +0,0 @@ -package list - -import ( - "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account" - "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb" - "github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid" - "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/encryptionkey" - "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric" - "github.com/gogo/protobuf/proto" - "hash/fnv" - "time" -) - -type MarshalledChange = []byte - -type ACLChangeBuilder interface { - UserAdd(identity string, encryptionKey encryptionkey.PubKey, permissions aclpb.ACLUserPermissions) error - AddId(id string) // TODO: this is only for testing -} - -type aclChangeBuilder struct { - aclState *ACLState - list ACLList - acc *account.AccountData - - aclData *aclpb.ACLData - id string - readKey *symmetric.Key - readKeyHash uint64 -} - -func newACLChangeBuilder() *aclChangeBuilder { - return &aclChangeBuilder{} -} - -func (c *aclChangeBuilder) Init(state *ACLState, list ACLList, acc *account.AccountData) { - c.aclState = state - c.list = list - c.acc = acc - - c.aclData = &aclpb.ACLData{} - // setting read key for further encryption etc - if state.currentReadKeyHash == 0 { - c.readKey, _ = symmetric.NewRandom() - - hasher := fnv.New64() - hasher.Write(c.readKey.Bytes()) - c.readKeyHash = hasher.Sum64() - } else { - c.readKey = c.aclState.userReadKeys[c.aclState.currentReadKeyHash] - c.readKeyHash = c.aclState.currentReadKeyHash - } -} - -func (c *aclChangeBuilder) AddId(id string) { - c.id = id -} - -func (c *aclChangeBuilder) UserAdd(identity string, encryptionKey encryptionkey.PubKey, permissions aclpb.ACLUserPermissions) error { - var allKeys []*symmetric.Key - if c.aclState.currentReadKeyHash != 0 { - for _, key := range c.aclState.userReadKeys { - allKeys = append(allKeys, key) - } - } else { - allKeys = append(allKeys, c.readKey) - } - - var encryptedKeys [][]byte - for _, k := range allKeys { - res, err := encryptionKey.Encrypt(k.Bytes()) - if err != nil { - return err - } - - encryptedKeys = append(encryptedKeys, res) - } - rawKey, err := encryptionKey.Raw() - if err != nil { - return err - } - ch := &aclpb.ACLContentValue{ - Value: &aclpb.ACLContentValue_UserAdd{ - UserAdd: &aclpb.ACLUserAdd{ - Identity: []byte(identity), - EncryptionKey: rawKey, - EncryptedReadKeys: encryptedKeys, - Permissions: permissions, - }, - }, - } - c.aclData.AclContent = append(c.aclData.AclContent, ch) - return nil -} - -func (c *aclChangeBuilder) BuildAndApply() (*ACLRecord, []byte, error) { - aclRecord := &aclpb.ACLRecord{ - PrevId: c.list.Head().Id, - CurrentReadKeyHash: c.readKeyHash, - Timestamp: int64(time.Now().Nanosecond()), - Identity: c.acc.Identity, - } - - marshalledData, err := proto.Marshal(c.aclData) - if err != nil { - return nil, nil, err - } - aclRecord.Data = marshalledData - err = c.aclState.applyRecord(aclRecord) - if err != nil { - return nil, nil, err - } - - fullMarshalledChange, err := proto.Marshal(aclRecord) - if err != nil { - return nil, nil, err - } - signature, err := c.acc.SignKey.Sign(fullMarshalledChange) - if err != nil { - return nil, nil, err - } - id, err := cid.NewCIDFromBytes(fullMarshalledChange) - if err != nil { - return nil, nil, err - } - ch := NewRecord(id, aclRecord) - ch.Model = c.aclData - ch.Sign = signature - - return ch, fullMarshalledChange, nil -} diff --git a/pkg/acl/list/list.go b/pkg/acl/list/list.go index d20d5b69..aad93a8f 100644 --- a/pkg/acl/list/list.go +++ b/pkg/acl/list/list.go @@ -5,10 +5,9 @@ import ( "errors" "fmt" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account" - "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb" + "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/common" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage" - "github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys" "sync" ) @@ -26,7 +25,7 @@ type RWLocker interface { type ACLList interface { RWLocker ID() string - Header() *aclpb.ACLHeader + Root() *aclrecordproto.ACLRoot Records() []*ACLRecord ACLState() *ACLState IsAfter(first string, second string) (bool, error) @@ -38,7 +37,7 @@ type ACLList interface { } type aclList struct { - header *aclpb.ACLHeader + root *aclrecordproto.ACLRoot records []*ACLRecord indexes map[string]int id string @@ -51,52 +50,50 @@ type aclList struct { } func BuildACLListWithIdentity(acc *account.AccountData, storage storage.ListStorage) (ACLList, error) { + id, err := storage.ID() + if err != nil { + return nil, err + } builder := newACLStateBuilderWithIdentity(acc.Decoder, acc) - return buildWithACLStateBuilder(builder, storage) + return build(id, builder, newACLRecordBuilder(id, common.NewKeychain()), storage) } func BuildACLList(decoder keys.Decoder, storage storage.ListStorage) (ACLList, error) { - return buildWithACLStateBuilder(newACLStateBuilder(decoder), storage) -} - -func buildWithACLStateBuilder(builder *aclStateBuilder, storage storage.ListStorage) (list ACLList, err error) { - header, err := storage.Root() - if err != nil { - return - } - id, err := storage.ID() + if err != nil { + return nil, err + } + return build(id, newACLStateBuilder(decoder), newACLRecordBuilder(id, common.NewKeychain()), storage) +} + +func build(id string, stateBuilder *aclStateBuilder, recBuilder ACLRecordBuilder, storage storage.ListStorage) (list ACLList, err error) { + rootWithId, err := storage.Root() if err != nil { return } - - rawRecord, err := storage.Head() + aclRecRoot, err := recBuilder.ConvertFromRaw(rootWithId) if err != nil { return } - keychain := common.NewKeychain() - record, err := NewFromRawRecord(rawRecord) + rawRecordWithId, err := storage.Head() if err != nil { return } - err = verifyRecord(keychain, rawRecord, record) + + record, err := recBuilder.ConvertFromRaw(rawRecordWithId) if err != nil { return } records := []*ACLRecord{record} - for record.Content.PrevId != "" { - rawRecord, err = storage.GetRawRecord(context.Background(), record.Content.PrevId) + for record.PrevId != "" { + rawRecordWithId, err = storage.GetRawRecord(context.Background(), record.PrevId) if err != nil { return } - record, err = NewFromRawRecord(rawRecord) - if err != nil { - return - } - err = verifyRecord(keychain, rawRecord, record) + record, err = recBuilder.ConvertFromRaw(rawRecordWithId) if err != nil { return } @@ -114,16 +111,16 @@ func buildWithACLStateBuilder(builder *aclStateBuilder, storage storage.ListStor indexes[records[len(records)/2].Id] = len(records) / 2 } - state, err := builder.Build(records) + state, err := stateBuilder.Build(records) if err != nil { return } list = &aclList{ - header: header, + root: aclRecRoot.Model.(*aclrecordproto.ACLRoot), records: records, indexes: indexes, - builder: builder, + builder: stateBuilder, aclState: state, id: id, RWMutex: sync.RWMutex{}, @@ -139,8 +136,8 @@ func (a *aclList) ID() string { return a.id } -func (a *aclList) Header() *aclpb.ACLHeader { - return a.header +func (a *aclList) Root() *aclrecordproto.ACLRoot { + return a.root } func (a *aclList) ACLState() *ACLState { @@ -191,26 +188,3 @@ func (a *aclList) IterateFrom(startId string, iterFunc IterFunc) { func (a *aclList) Close() (err error) { return nil } - -func verifyRecord(keychain *common.Keychain, rawRecord *aclpb.RawACLRecord, record *ACLRecord) (err error) { - identityKey, err := keychain.GetOrAdd(record.Identity) - if err != nil { - return - } - - // verifying signature - res, err := identityKey.Verify(rawRecord.Payload, rawRecord.Signature) - if err != nil { - return - } - if !res { - err = ErrInvalidSignature - return - } - - // verifying ID - if !cid.VerifyCID(rawRecord.Payload, rawRecord.Id) { - err = ErrIncorrectCID - } - return -} diff --git a/pkg/acl/list/record.go b/pkg/acl/list/record.go index 04f4abbf..abb37736 100644 --- a/pkg/acl/list/record.go +++ b/pkg/acl/list/record.go @@ -1,65 +1,12 @@ package list -import ( - "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto" - "github.com/gogo/protobuf/proto" -) - type ACLRecord struct { - Id string - Content *aclrecordproto.ACLRecord - Identity string - Model interface{} - Sign []byte + Id string + PrevId string + CurrentReadKeyHash uint64 + Timestamp int64 + Data []byte + Identity []byte + Model interface{} + Signature []byte } - -func NewRecord(id string, aclRecord *aclrecordproto.ACLRecord) *ACLRecord { - return &ACLRecord{ - Id: id, - Content: aclRecord, - Identity: string(aclRecord.Identity), - } -} - -func NewFromRawRecord(rawRecWithId *aclrecordproto.RawACLRecordWithId) (aclRec *ACLRecord, err error) { - rawRec := &aclrecordproto.RawACLRecord{} - err = proto.Unmarshal(rawRecWithId.Payload, rawRec) - if err != nil { - return - } - - protoAclRec := &aclrecordproto.ACLRecord{} - err = proto.Unmarshal(rawRec.Payload, protoAclRec) - if err != nil { - return - } - - return &ACLRecord{ - Id: rawRecWithId.Id, - Content: protoAclRec, - Sign: rawRec.Signature, - Identity: string(protoAclRec.Identity), - }, nil -} - -func NewFromRawRoot(rawRecWithId *aclrecordproto.RawACLRecordWithId) (aclRec *ACLRecord, err error) { - rawRec := &aclrecordproto.RawACLRecord{} - err = proto.Unmarshal(rawRecWithId.Payload, rawRec) - if err != nil { - return - } - - protoAclRec := &aclrecordproto.ACLRecord{} - err = proto.Unmarshal(rawRec.Payload, protoAclRec) - if err != nil { - return - } - - return &ACLRecord{ - Id: rawRecWithId.Id, - Content: protoAclRec, - Sign: rawRec.Signature, - Identity: string(protoAclRec.Identity), - }, nil -} - diff --git a/util/keys/symmetric/symmetric.go b/util/keys/symmetric/symmetric.go index 22648769..711f1fdd 100644 --- a/util/keys/symmetric/symmetric.go +++ b/util/keys/symmetric/symmetric.go @@ -5,6 +5,7 @@ import ( "crypto/cipher" "crypto/rand" "fmt" + "github.com/minio/sha256-simd" mbase "github.com/multiformats/go-multibase" ) @@ -21,6 +22,12 @@ type Key struct { raw []byte } +func DeriveFromBytes(bytes []byte) (*Key, error) { + bArray := sha256.Sum256(bytes) + bSlice := bArray[:] + return FromBytes(bSlice) +} + func (k *Key) Equals(otherKey *Key) bool { otherRaw := otherKey.raw keyRaw := k.raw