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