Add test for user join build and fix bugs

This commit is contained in:
mcrakhman 2022-10-28 13:01:20 +02:00 committed by Mikhail Iudin
parent 2946c050b9
commit 3046a44d12
No known key found for this signature in database
GPG Key ID: FAAAA8BAABDFF1C0
9 changed files with 136 additions and 65 deletions

View File

@ -825,7 +825,7 @@ func (m *ACLUserJoin) GetEncryptedReadKeys() [][]byte {
type ACLUserRemove struct {
Identity []byte `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"`
ReadKeyReplaces []*ACLReadKeyReplace `protobuf:"bytes,3,rep,name=readKeyReplaces,proto3" json:"readKeyReplaces,omitempty"`
ReadKeyReplaces []*ACLReadKeyReplace `protobuf:"bytes,2,rep,name=readKeyReplaces,proto3" json:"readKeyReplaces,omitempty"`
}
func (m *ACLUserRemove) Reset() { *m = ACLUserRemove{} }
@ -1058,14 +1058,14 @@ var fileDescriptor_14abe0d1b4206d54 = []byte{
0xc2, 0xb5, 0xdc, 0xc3, 0xc9, 0x64, 0xc2, 0x5c, 0x65, 0x2f, 0x66, 0xa3, 0x28, 0x4c, 0xe6, 0xc6,
0x0e, 0x74, 0x32, 0xad, 0xf2, 0x39, 0x5f, 0xf2, 0x6d, 0x96, 0xe3, 0x60, 0x8b, 0x1c, 0x4e, 0x94,
0x9d, 0x52, 0x32, 0x25, 0x77, 0x6d, 0xe7, 0x19, 0x1c, 0x27, 0x33, 0x80, 0xb0, 0x70, 0x4e, 0xdd,
0xec, 0x06, 0x3f, 0x28, 0xeb, 0x47, 0x4a, 0x20, 0x52, 0x4d, 0x72, 0x7e, 0x44, 0x70, 0xaf, 0x06,
0xec, 0xde, 0x3f, 0x28, 0xeb, 0x47, 0x4a, 0x20, 0x52, 0x4d, 0x72, 0x7e, 0x44, 0x70, 0xaf, 0x06,
0xdb, 0x83, 0x90, 0x9b, 0x9e, 0xc2, 0xc6, 0xe6, 0xa7, 0xd0, 0x59, 0xc1, 0xfd, 0x2d, 0x63, 0x7e,
0x27, 0x91, 0x4a, 0xfb, 0x98, 0x6f, 0xda, 0x3e, 0x0f, 0x1f, 0x03, 0xae, 0x43, 0xb0, 0x05, 0x07,
0x63, 0x6f, 0xc1, 0xfd, 0xae, 0x81, 0x01, 0x0e, 0x5f, 0x08, 0x2e, 0x99, 0xe8, 0x22, 0xb5, 0x56,
0x7c, 0x99, 0xe8, 0x9a, 0x4f, 0x3e, 0xfa, 0xfd, 0xa6, 0x87, 0x5e, 0xdf, 0xf4, 0xd0, 0x3f, 0x37,
0x3d, 0xf4, 0xf3, 0x6d, 0xcf, 0x78, 0x7d, 0xdb, 0x33, 0xfe, 0xbe, 0xed, 0x19, 0xdf, 0x9f, 0x6c,
0xfe, 0x3d, 0xf7, 0xf2, 0x50, 0x7f, 0x7c, 0xf2, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa5, 0x4a,
0x77, 0x11, 0xf0, 0x09, 0x00, 0x00,
0xfe, 0x3d, 0xf7, 0xf2, 0x50, 0x7f, 0x7c, 0xf2, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x80, 0xdf,
0xf6, 0x6c, 0xf0, 0x09, 0x00, 0x00,
}
func (m *RawACLRecord) Marshal() (dAtA []byte, err error) {
@ -1752,7 +1752,7 @@ func (m *ACLUserRemove) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i = encodeVarintAclrecord(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x1a
dAtA[i] = 0x12
}
}
if len(m.Identity) > 0 {
@ -4252,7 +4252,7 @@ func (m *ACLUserRemove) Unmarshal(dAtA []byte) error {
m.Identity = []byte{}
}
iNdEx = postIndex
case 3:
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ReadKeyReplaces", wireType)
}

View File

@ -80,7 +80,7 @@ message ACLUserJoin {
message ACLUserRemove {
bytes identity = 1;
repeated ACLReadKeyReplace readKeyReplaces = 3;
repeated ACLReadKeyReplace readKeyReplaces = 2;
}
message ACLReadKeyReplace {

View File

@ -7,6 +7,7 @@ import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/signingkey"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/symmetric"
"github.com/gogo/protobuf/proto"
"time"
)
type ACLRecordBuilder interface {
@ -35,7 +36,7 @@ func (a *aclRecordBuilder) BuildUserJoin(acceptPrivKeyBytes []byte, encSymKeyByt
if err != nil {
return
}
encSymKey, err := symmetric.DeriveFromBytes(encSymKeyBytes)
encSymKey, err := symmetric.FromBytes(encSymKeyBytes)
if err != nil {
return
}
@ -74,17 +75,31 @@ func (a *aclRecordBuilder) BuildUserJoin(acceptPrivKeyBytes []byte, encSymKeyByt
AcceptPubKey: acceptPubKeyBytes,
EncryptedReadKeys: symKeys,
}
marshalledJoin, err := userJoin.Marshal()
aclData := &aclrecordproto.ACLData{AclContent: []*aclrecordproto.ACLContentValue{
{Value: &aclrecordproto.ACLContentValue_UserJoin{UserJoin: userJoin}},
}}
marshalledJoin, err := aclData.Marshal()
if err != nil {
return
}
joinSignature, err := signPrivKey.Sign(marshalledJoin)
aclRecord := &aclrecordproto.ACLRecord{
PrevId: state.LastRecordId(),
Identity: state.Identity(),
Data: marshalledJoin,
CurrentReadKeyHash: state.CurrentReadKeyHash(),
Timestamp: time.Now().UnixNano(),
}
marshalledRecord, err := aclRecord.Marshal()
if err != nil {
return
}
recSignature, err := signPrivKey.Sign(marshalledRecord)
if err != nil {
return
}
rec = &aclrecordproto.RawACLRecord{
Payload: marshalledJoin,
Signature: joinSignature,
Payload: marshalledRecord,
Signature: recSignature,
}
return
}

View File

@ -0,0 +1,50 @@
package list
import (
"context"
account "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/account"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/common"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/testutils/acllistbuilder"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/cid"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/signingkey"
"github.com/stretchr/testify/require"
"testing"
)
func TestAclRecordBuilder_BuildUserJoin(t *testing.T) {
st, err := acllistbuilder.NewListStorageWithTestName("userjoinexample.yml")
require.NoError(t, err, "building storage should not result in error")
keychain := st.(*acllistbuilder.ACLListStorageBuilder).GetKeychain()
identity := keychain.GeneratedIdentities["D"]
signPrivKey := keychain.SigningKeysByYAMLName["D"]
encPrivKey := keychain.EncryptionKeysByYAMLName["D"]
acc := &account.AccountData{
Identity: []byte(identity),
SignKey: signPrivKey,
EncKey: encPrivKey,
}
aclList, err := BuildACLListWithIdentity(acc, st)
require.NoError(t, err, "building acl list should be without error")
recordBuilder := newACLRecordBuilder(aclList.ID(), common.NewKeychain())
rk, err := keychain.GetKey("key.Read.EncKey").(*acllistbuilder.SymKey).Key.Raw()
require.NoError(t, err)
privKey, err := keychain.GetKey("key.Sign.Onetime1").(signingkey.PrivKey).Raw()
require.NoError(t, err)
userJoin, err := recordBuilder.BuildUserJoin(privKey, rk, aclList.ACLState())
require.NoError(t, err)
marshalledJoin, err := userJoin.Marshal()
require.NoError(t, err)
id, err := cid.NewCIDFromBytes(marshalledJoin)
require.NoError(t, err)
rawRec := &aclrecordproto.RawACLRecordWithId{
Payload: marshalledJoin,
Id: id,
}
err = aclList.AddRawRecords(context.Background(), []*aclrecordproto.RawACLRecordWithId{rawRec})
require.NoError(t, err)
require.Equal(t, aclrecordproto.ACLUserPermissions_Writer, aclList.ACLState().UserStates()[identity].Permissions)
}

View File

@ -184,6 +184,7 @@ func (st *ACLState) applyRoot(root *aclrecordproto.ACLRoot) (err error) {
EncryptionKey: root.EncryptionKey,
Permissions: aclrecordproto.ACLUserPermissions_Admin,
}
st.currentReadKeyHash = root.CurrentReadKeyHash
st.userStates[string(root.Identity)] = userState
st.totalReadKeys++
return
@ -192,13 +193,18 @@ func (st *ACLState) applyRoot(root *aclrecordproto.ACLRoot) (err error) {
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()
var encPrivKey []byte
encPrivKey, err = st.encryptionKey.Raw()
if err != nil {
return
}
var signPrivKey []byte
signPrivKey, err = st.signingKey.Raw()
if err != nil {
return
}
readKey, err = aclrecordproto.ACLReadKeyDerive([]byte(st.identity), encPubKey)
readKey, err = aclrecordproto.ACLReadKeyDerive(signPrivKey, encPrivKey)
if err != nil {
return
}
@ -217,7 +223,6 @@ func (st *ACLState) saveReadKeyFromRoot(root *aclrecordproto.ACLRoot) (err error
if hasher.Sum64() != root.CurrentReadKeyHash {
return ErrIncorrectRoot
}
st.currentReadKeyHash = root.CurrentReadKeyHash
st.userReadKeys[root.CurrentReadKeyHash] = readKey
return
@ -451,3 +456,7 @@ func (st *ACLState) UserKeys() (encKey encryptionkey.PrivKey, signKey signingkey
func (st *ACLState) Identity() []byte {
return []byte(st.identity)
}
func (st *ACLState) LastRecordId() string {
return st.lastRecordId
}

View File

@ -16,28 +16,26 @@ type SymKey struct {
}
type YAMLKeychain struct {
SigningKeysByYAMLIdentity map[string]signingkey2.PrivKey
SigningKeysByRealIdentity map[string]signingkey2.PrivKey
EncryptionKeysByYAMLIdentity map[string]encryptionkey2.PrivKey
ReadKeysByYAMLIdentity map[string]*SymKey
ReadKeysByHash map[uint64]*SymKey
GeneratedIdentities map[string]string
DerivedIdentity string
SigningKeysByYAMLName map[string]signingkey2.PrivKey
SigningKeysByRealIdentity map[string]signingkey2.PrivKey
EncryptionKeysByYAMLName map[string]encryptionkey2.PrivKey
ReadKeysByYAMLName map[string]*SymKey
ReadKeysByHash map[uint64]*SymKey
GeneratedIdentities map[string]string
}
func NewKeychain() *YAMLKeychain {
return &YAMLKeychain{
SigningKeysByYAMLIdentity: map[string]signingkey2.PrivKey{},
SigningKeysByRealIdentity: map[string]signingkey2.PrivKey{},
EncryptionKeysByYAMLIdentity: map[string]encryptionkey2.PrivKey{},
GeneratedIdentities: map[string]string{},
ReadKeysByYAMLIdentity: map[string]*SymKey{},
ReadKeysByHash: map[uint64]*SymKey{},
SigningKeysByYAMLName: map[string]signingkey2.PrivKey{},
SigningKeysByRealIdentity: map[string]signingkey2.PrivKey{},
EncryptionKeysByYAMLName: map[string]encryptionkey2.PrivKey{},
GeneratedIdentities: map[string]string{},
ReadKeysByYAMLName: map[string]*SymKey{},
ReadKeysByHash: map[uint64]*SymKey{},
}
}
func (k *YAMLKeychain) ParseKeys(keys *Keys) {
k.DerivedIdentity = keys.Derived
for _, encKey := range keys.Enc {
k.AddEncryptionKey(encKey)
}
@ -52,7 +50,7 @@ func (k *YAMLKeychain) ParseKeys(keys *Keys) {
}
func (k *YAMLKeychain) AddEncryptionKey(key *Key) {
if _, exists := k.EncryptionKeysByYAMLIdentity[key.Name]; exists {
if _, exists := k.EncryptionKeysByYAMLName[key.Name]; exists {
return
}
var (
@ -70,11 +68,11 @@ func (k *YAMLKeychain) AddEncryptionKey(key *Key) {
panic(err)
}
}
k.EncryptionKeysByYAMLIdentity[key.Name] = newPrivKey
k.EncryptionKeysByYAMLName[key.Name] = newPrivKey
}
func (k *YAMLKeychain) AddSigningKey(key *Key) {
if _, exists := k.SigningKeysByYAMLIdentity[key.Name]; exists {
if _, exists := k.SigningKeysByYAMLName[key.Name]; exists {
return
}
var (
@ -95,7 +93,7 @@ func (k *YAMLKeychain) AddSigningKey(key *Key) {
pubKey = newPrivKey.GetPublic()
}
k.SigningKeysByYAMLIdentity[key.Name] = newPrivKey
k.SigningKeysByYAMLName[key.Name] = newPrivKey
rawPubKey, err := pubKey.Raw()
if err != nil {
panic(err)
@ -107,7 +105,7 @@ func (k *YAMLKeychain) AddSigningKey(key *Key) {
}
func (k *YAMLKeychain) AddReadKey(key *Key) {
if _, exists := k.ReadKeysByYAMLIdentity[key.Name]; exists {
if _, exists := k.ReadKeysByYAMLName[key.Name]; exists {
return
}
@ -121,8 +119,8 @@ func (k *YAMLKeychain) AddReadKey(key *Key) {
panic("should be able to generate symmetric key")
}
} else if key.Value == "derived" {
signKey, _ := k.SigningKeysByYAMLIdentity[k.DerivedIdentity].Raw()
encKey, _ := k.EncryptionKeysByYAMLIdentity[k.DerivedIdentity].Raw()
signKey, _ := k.SigningKeysByYAMLName[key.Name].Raw()
encKey, _ := k.EncryptionKeysByYAMLName[key.Name].Raw()
rkey, err = aclrecordproto.ACLReadKeyDerive(signKey, encKey)
if err != nil {
panic("should be able to derive symmetric key")
@ -137,7 +135,7 @@ func (k *YAMLKeychain) AddReadKey(key *Key) {
hasher := fnv.New64()
hasher.Write(rkey.Bytes())
k.ReadKeysByYAMLIdentity[key.Name] = &SymKey{
k.ReadKeysByYAMLName[key.Name] = &SymKey{
Hash: hasher.Sum64(),
Key: rkey,
}
@ -174,15 +172,15 @@ func (k *YAMLKeychain) GetKey(key string) interface{} {
switch parts[1] {
case "Sign":
if key, exists := k.SigningKeysByYAMLIdentity[name]; exists {
if key, exists := k.SigningKeysByYAMLName[name]; exists {
return key
}
case "Enc":
if key, exists := k.EncryptionKeysByYAMLIdentity[name]; exists {
if key, exists := k.EncryptionKeysByYAMLName[name]; exists {
return key
}
case "Read":
if key, exists := k.ReadKeysByYAMLIdentity[name]; exists {
if key, exists := k.ReadKeysByYAMLName[name]; exists {
return key
}
default:

View File

@ -10,7 +10,6 @@ import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/encryptionkey"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/signingkey"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/symmetric"
"hash/fnv"
"io/ioutil"
"path"
"time"
@ -127,7 +126,7 @@ func (t *ACLListStorageBuilder) parseRecord(rec *Record, prevId string) *aclreco
Identity: []byte(t.keychain.GetIdentity(rec.Identity)),
Data: bytes,
CurrentReadKeyHash: k.Hash,
Timestamp: time.Now().Unix(),
Timestamp: time.Now().UnixNano(),
}
}
@ -155,7 +154,7 @@ func (t *ACLListStorageBuilder) parseACLChange(ch *ACLChange) (convCh *aclrecord
encKey := t.keychain.GetKey(join.EncryptionKey).(encryptionkey.PrivKey)
rawKey, _ := encKey.GetPublic().Raw()
idKey, _ := t.keychain.SigningKeysByYAMLIdentity[join.Identity].GetPublic().Raw()
idKey, _ := t.keychain.SigningKeysByYAMLName[join.Identity].GetPublic().Raw()
signKey := t.keychain.GetKey(join.AcceptKey).(signingkey.PrivKey)
signature, err := signKey.Sign(idKey)
if err != nil {
@ -208,7 +207,7 @@ func (t *ACLListStorageBuilder) parseACLChange(ch *ACLChange) (convCh *aclrecord
var replaces []*aclrecordproto.ACLReadKeyReplace
for _, id := range remove.IdentitiesLeft {
encKey := t.keychain.EncryptionKeysByYAMLIdentity[id]
encKey := t.keychain.EncryptionKeysByYAMLName[id]
rawEncKey, _ := encKey.GetPublic().Raw()
encReadKey, err := encKey.GetPublic().Encrypt(newReadKey.Key.Bytes())
if err != nil {
@ -281,18 +280,16 @@ func (t *ACLListStorageBuilder) traverseFromHead(f func(rec *aclrecordproto.ACLR
}
func (t *ACLListStorageBuilder) parseRoot(root *Root) (rawRoot *aclrecordproto.RawACLRecordWithId) {
rawSignKey, _ := t.keychain.SigningKeysByYAMLIdentity[root.Identity].GetPublic().Raw()
rawEncKey, _ := t.keychain.EncryptionKeysByYAMLIdentity[root.Identity].GetPublic().Raw()
readKey, _ := aclrecordproto.ACLReadKeyDerive(rawSignKey, rawEncKey)
hasher := fnv.New64()
hasher.Write(readKey.Bytes())
rawSignKey, _ := t.keychain.SigningKeysByYAMLName[root.Identity].GetPublic().Raw()
rawEncKey, _ := t.keychain.EncryptionKeysByYAMLName[root.Identity].GetPublic().Raw()
readKey := t.keychain.ReadKeysByYAMLName[root.Identity]
aclRoot := &aclrecordproto.ACLRoot{
Identity: rawSignKey,
EncryptionKey: rawEncKey,
SpaceId: root.SpaceId,
EncryptedReadKey: nil,
DerivationScheme: "scheme",
CurrentReadKeyHash: hasher.Sum64(),
CurrentReadKeyHash: readKey.Hash,
}
return t.createRaw(aclRoot, rawSignKey)
}

View File

@ -7,24 +7,23 @@ records:
- userInvite:
acceptKey: key.Sign.Onetime1
encryptionKey: key.Read.EncKey
encryptedReadKeys: [key.Read.1]
encryptedReadKeys: [key.Read.A]
permissions: writer
- userAdd:
identity: C
permission: reader
encryptionKey: key.Enc.C
encryptedReadKeys: [key.Read.1]
readKey: key.Read.1
encryptedReadKeys: [key.Read.A]
readKey: key.Read.A
- identity: B
aclChanges:
- userJoin:
identity: B
encryptionKey: key.Enc.B
acceptKey: key.Sign.Onetime1
encryptedReadKeys: [key.Read.1]
readKey: key.Read.1
encryptedReadKeys: [key.Read.A]
readKey: key.Read.A
keys:
Derived: A
Enc:
- name: A
value: generated
@ -32,6 +31,8 @@ keys:
value: generated
- name: C
value: generated
- name: D
value: generated
- name: Onetime1
value: generated
Sign:
@ -41,10 +42,12 @@ keys:
value: generated
- name: C
value: generated
- name: D
value: generated
- name: Onetime1
value: generated
Read:
- name: 1
- name: A
value: derived
- name: EncKey
value: generated

View File

@ -7,22 +7,22 @@ records:
- userInvite:
acceptKey: key.Sign.Onetime1
encryptionKey: key.Read.EncKey
encryptedReadKeys: [key.Read.1]
encryptedReadKeys: [key.Read.A]
permissions: writer
- userAdd:
identity: C
permission: reader
encryptionKey: key.Enc.C
encryptedReadKeys: [key.Read.1]
readKey: key.Read.1
encryptedReadKeys: [key.Read.A]
readKey: key.Read.A
- identity: B
aclChanges:
- userJoin:
identity: B
encryptionKey: key.Enc.B
acceptKey: key.Sign.Onetime1
encryptedReadKeys: [key.Read.1]
readKey: key.Read.1
encryptedReadKeys: [key.Read.A]
readKey: key.Read.A
- identity: A
aclChanges:
- userRemove:
@ -31,7 +31,6 @@ records:
identitiesLeft: [A, C]
readKey: key.Read.2
keys:
Derived: A
Enc:
- name: A
value: generated
@ -51,7 +50,7 @@ keys:
- name: Onetime1
value: generated
Read:
- name: 1
- name: A
value: derived
- name: 2
value: generated