diff --git a/merkletree/pad.go b/merkletree/pad.go index bb31951..08e7dac 100644 --- a/merkletree/pad.go +++ b/merkletree/pad.go @@ -1,6 +1,7 @@ package merkletree import ( + "bytes" "crypto/subtle" "errors" @@ -91,8 +92,7 @@ func (pad *PAD) Update(policies *Policies) { } func (pad *PAD) Set(name string, value []byte) error { - index, _ := pad.computePrivateIndex(name, pad.policies.vrfPrivateKey) - return pad.tree.Set(index, name, value) + return pad.tree.Set(pad.Index(name), name, value) } func (pad *PAD) Lookup(name string) (*AuthenticationPath, error) { @@ -121,11 +121,13 @@ func (pad *PAD) LatestSTR() *SignedTreeRoot { return pad.latestSTR } -func (pad *PAD) TB(name string, value []byte) (*TemporaryBinding, error) { +func (pad *PAD) Sign(msg ...[]byte) []byte { + return pad.signKey.Sign(bytes.Join(msg, nil)) +} + +func (pad *PAD) Index(name string) []byte { index, _ := pad.computePrivateIndex(name, pad.policies.vrfPrivateKey) - tb := NewTB(pad.signKey, pad.latestSTR.Signature, index, value) - err := pad.tree.Set(index, name, value) - return tb, err + return index } // reshuffle recomputes indices of keys and store them with their values in new @@ -139,8 +141,7 @@ func (pad *PAD) reshuffle() { panic(err) } pad.tree.visitLeafNodes(func(n *userLeafNode) { - newIndex, _ := pad.computePrivateIndex(n.key, pad.policies.vrfPrivateKey) - if err := newTree.Set(newIndex, n.key, n.value); err != nil { + if err := newTree.Set(pad.Index(n.key), n.key, n.value); err != nil { panic(err) } }) diff --git a/merkletree/tb.go b/merkletree/tb.go deleted file mode 100644 index b9ec492..0000000 --- a/merkletree/tb.go +++ /dev/null @@ -1,27 +0,0 @@ -package merkletree - -import "github.com/coniks-sys/coniks-go/crypto/sign" - -type TemporaryBinding struct { - Index []byte - Value []byte - Signature []byte -} - -func NewTB(key sign.PrivateKey, strSig, index, value []byte) *TemporaryBinding { - tb := &TemporaryBinding{ - Index: index, - Value: value, - } - tbPreSig := tb.Serialize(strSig) - tb.Signature = key.Sign(tbPreSig) - return tb -} - -func (tb *TemporaryBinding) Serialize(strSig []byte) []byte { - var tbBytes []byte - tbBytes = append(tbBytes, strSig...) - tbBytes = append(tbBytes, tb.Index...) - tbBytes = append(tbBytes, tb.Value...) - return tbBytes -} diff --git a/merkletree/tb_test.go b/merkletree/tb_test.go deleted file mode 100644 index 7c05f40..0000000 --- a/merkletree/tb_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package merkletree - -import ( - "bytes" - "testing" -) - -func TestTB(t *testing.T) { - key := "key" - val := []byte("value") - - pad, err := NewPAD(NewPolicies(3, vrfPrivKey1), signKey, 3) - if err != nil { - t.Fatal(err) - } - tb, err := pad.TB(key, val) - if err != nil { - t.Fatal(err) - } - - pk, ok := pad.signKey.Public() - if !ok { - t.Fatal("Couldn't retrieve public-key.") - } - tbb := tb.Serialize(pad.latestSTR.Signature) - if !pk.Verify(tbb, tb.Signature) { - t.Fatal("Couldn't validate signature") - } - // verify VRF index of TB - if !bytes.Equal(vrfPrivKey1.Compute([]byte(key)), tb.Index) { - t.Error("VRF verification returns false") - } - - // create next epoch and see if the TB is inserted as promised: - pad.Update(nil) - - ap, err := pad.Lookup(key) - // compare TB's index with authentication path's index (after Update): - if !bytes.Equal(ap.LookupIndex, tb.Index) || - !bytes.Equal(ap.Leaf.Value, tb.Value) { - t.Error("Value wasn't inserted as promised") - } - // verify auth path - if !ap.Verify(pad.LatestSTR().TreeHash) { - t.Error("Proof of inclusion verification failed.") - } -} diff --git a/protocol/directory.go b/protocol/directory.go index 7606cca..9a8982f 100644 --- a/protocol/directory.go +++ b/protocol/directory.go @@ -11,7 +11,7 @@ import ( type ConiksDirectory struct { pad *merkletree.PAD useTBs bool - tbs map[string]*merkletree.TemporaryBinding + tbs map[string]*TemporaryBinding policies *merkletree.Policies } @@ -32,7 +32,7 @@ func NewDirectory(epDeadline merkletree.TimeStamp, vrfKey vrf.PrivateKey, d.pad = pad d.useTBs = useTBs if useTBs { - d.tbs = make(map[string]*merkletree.TemporaryBinding) + d.tbs = make(map[string]*TemporaryBinding) } return d } @@ -57,9 +57,17 @@ func (d *ConiksDirectory) LatestSTR() *merkletree.SignedTreeRoot { return d.pad.LatestSTR() } +func (d *ConiksDirectory) NewTB(name string, key []byte) *TemporaryBinding { + index := d.pad.Index(name) + return &TemporaryBinding{ + Index: index, + Value: key, + Signature: d.pad.Sign(d.LatestSTR().Signature, index, key), + } +} + func (d *ConiksDirectory) Register(req *RegistrationRequest) ( *Response, ErrorCode) { - // make sure the request is well-formed if len(req.Username) <= 0 || len(req.Key) <= 0 { return NewErrorResponse(ErrorMalformedClientMessage), @@ -75,26 +83,26 @@ func (d *ConiksDirectory) Register(req *RegistrationRequest) ( if bytes.Equal(ap.LookupIndex, ap.Leaf.Index) { return NewRegistrationProof(ap, d.LatestSTR(), nil, ErrorNameExisted) } + + var tb *TemporaryBinding + if d.useTBs { // also check the temporary bindings array // currently the server allows only one registration/key change per epoch - if tb := d.tbs[req.Username]; tb != nil { + if tb = d.tbs[req.Username]; tb != nil { return NewRegistrationProof(ap, d.LatestSTR(), tb, ErrorNameExisted) } + tb = d.NewTB(req.Username, req.Key) + } - // insert new data to the directory on-the-fly - tb, err := d.pad.TB(req.Username, req.Key) - if err != nil { - return NewErrorResponse(ErrorDirectory), ErrorDirectory - } + if err = d.pad.Set(req.Username, req.Key); err != nil { + return NewErrorResponse(ErrorDirectory), ErrorDirectory + } + + if tb != nil { d.tbs[req.Username] = tb - return NewRegistrationProof(ap, d.LatestSTR(), tb, Success) - } else { - if err = d.pad.Set(req.Username, req.Key); err != nil { - return NewErrorResponse(ErrorDirectory), ErrorDirectory - } - return NewRegistrationProof(ap, d.LatestSTR(), nil, Success) } + return NewRegistrationProof(ap, d.LatestSTR(), tb, Success) } func (d *ConiksDirectory) KeyLookup(req *KeyLookupRequest) ( diff --git a/protocol/message.go b/protocol/message.go index 5d11b45..00a3011 100644 --- a/protocol/message.go +++ b/protocol/message.go @@ -67,7 +67,7 @@ type DirectoryResponse interface { type DirectoryProof struct { AP *m.AuthenticationPath STR *m.SignedTreeRoot - TB *m.TemporaryBinding `json:",omitempty"` + TB *TemporaryBinding `json:",omitempty"` } type DirectoryProofs struct { @@ -83,7 +83,7 @@ var _ DirectoryResponse = (*DirectoryProof)(nil) var _ DirectoryResponse = (*DirectoryProofs)(nil) func NewRegistrationProof(ap *m.AuthenticationPath, str *m.SignedTreeRoot, - tb *m.TemporaryBinding, e ErrorCode) (*Response, ErrorCode) { + tb *TemporaryBinding, e ErrorCode) (*Response, ErrorCode) { return &Response{ Error: e, DirectoryResponse: &DirectoryProof{ @@ -95,7 +95,7 @@ func NewRegistrationProof(ap *m.AuthenticationPath, str *m.SignedTreeRoot, } func NewKeyLookupProof(ap *m.AuthenticationPath, str *m.SignedTreeRoot, - tb *m.TemporaryBinding, e ErrorCode) (*Response, ErrorCode) { + tb *TemporaryBinding, e ErrorCode) (*Response, ErrorCode) { return &Response{ Error: e, DirectoryResponse: &DirectoryProof{ diff --git a/protocol/tb.go b/protocol/tb.go new file mode 100644 index 0000000..09d1173 --- /dev/null +++ b/protocol/tb.go @@ -0,0 +1,7 @@ +package protocol + +type TemporaryBinding struct { + Index []byte + Value []byte + Signature []byte +}