From 8d42521df3df4d33939335f7cd03147a5e0f7d5f Mon Sep 17 00:00:00 2001 From: Arlo Breault Date: Sun, 18 Dec 2016 22:35:18 -0800 Subject: [PATCH 1/7] Use protocol.DirSTR for policy unmarshalling * Closes #135 --- client/encoding.go | 8 ------ merkletree/str.go | 41 +----------------------------- protocol/consistencychecks.go | 21 ++++++--------- protocol/consistencychecks_test.go | 15 +++++++---- protocol/directory.go | 12 ++++----- protocol/directory_test.go | 6 ++--- protocol/message.go | 12 ++++----- protocol/str.go | 23 +++++++++++++++++ protocol/str_test.go | 23 +++++++++++++++++ 9 files changed, 80 insertions(+), 81 deletions(-) create mode 100644 protocol/str.go create mode 100644 protocol/str_test.go diff --git a/client/encoding.go b/client/encoding.go index bbacdfb..ab2a5c8 100644 --- a/client/encoding.go +++ b/client/encoding.go @@ -3,7 +3,6 @@ package client import ( "encoding/json" - "github.com/coniks-sys/coniks-go/merkletree" p "github.com/coniks-sys/coniks-go/protocol" ) @@ -43,13 +42,6 @@ func UnmarshalResponse(t int, msg []byte) *p.Response { Error: p.ErrMalformedDirectoryMessage, } } - policies := &p.Policies{} - if err := json.Unmarshal([]byte(response.STR.Ad.(merkletree.RawAd)), policies); err != nil { - return &p.Response{ - Error: p.ErrMalformedDirectoryMessage, - } - } - response.STR.Ad = policies return &p.Response{ Error: res.Error, DirectoryResponse: response, diff --git a/merkletree/str.go b/merkletree/str.go index 9d78b09..26d5982 100644 --- a/merkletree/str.go +++ b/merkletree/str.go @@ -3,8 +3,6 @@ package merkletree import ( "bytes" - "encoding/json" - "github.com/coniks-sys/coniks-go/crypto" "github.com/coniks-sys/coniks-go/crypto/sign" "github.com/coniks-sys/coniks-go/utils" @@ -29,44 +27,7 @@ type SignedTreeRoot struct { PreviousEpoch uint64 PreviousSTRHash []byte Signature []byte - Ad AssocData -} - -// TODO(arlolra): Look into using a DirSTR instead, to avoid this mess. - -// RawAd makes json.RawMessage implement the AssocData interface. -type RawAd json.RawMessage - -// Serialize should never be called. -func (r RawAd) Serialize() []byte { - panic("[str] Should never be called") - return nil -} - -// UnmarshalJSON returns the STR with a json.RawMessage as AssocData for -// further unmarshalling by the caller. -func (str *SignedTreeRoot) UnmarshalJSON(m []byte) error { - type Str struct { - tree *MerkleTree - TreeHash []byte - Epoch uint64 - PreviousEpoch uint64 - PreviousSTRHash []byte - Signature []byte - Ad json.RawMessage - } - hStr := &Str{} - if err := json.Unmarshal(m, hStr); err != nil { - return err - } - str.tree = hStr.tree - str.TreeHash = hStr.TreeHash - str.Epoch = hStr.Epoch - str.PreviousEpoch = hStr.PreviousEpoch - str.PreviousSTRHash = hStr.PreviousSTRHash - str.Signature = hStr.Signature - str.Ad = RawAd(hStr.Ad) - return nil + Ad AssocData `json:"-"` } // NewSTR constructs a SignedTreeRoot with the given signing key pair, diff --git a/protocol/consistencychecks.go b/protocol/consistencychecks.go index ba4a19e..856b706 100644 --- a/protocol/consistencychecks.go +++ b/protocol/consistencychecks.go @@ -26,7 +26,7 @@ import ( // client request. type ConsistencyChecks struct { // SavedSTR stores the latest verified signed tree root. - SavedSTR *m.SignedTreeRoot + SavedSTR *DirSTR Bindings map[string][]byte // extensions settings @@ -39,7 +39,7 @@ type ConsistencyChecks struct { // NewCC creates an instance of ConsistencyChecks using // a CONIKS directory's pinned STR at epoch 0, or // the consistency state read from persistent storage. -func NewCC(savedSTR *m.SignedTreeRoot, useTBs bool, signKey sign.PublicKey) *ConsistencyChecks { +func NewCC(savedSTR *DirSTR, useTBs bool, signKey sign.PublicKey) *ConsistencyChecks { // TODO: see #110 if !useTBs { panic("[coniks] Currently the server is forced to use TBs") @@ -101,7 +101,7 @@ func (cc *ConsistencyChecks) HandleResponse(requestType int, msg *Response, } func (cc *ConsistencyChecks) updateSTR(requestType int, msg *Response) error { - var str *m.SignedTreeRoot + var str *DirSTR switch requestType { case RegistrationType, KeyLookupType: str = msg.DirectoryResponse.(*DirectoryProof).STR @@ -132,7 +132,7 @@ func (cc *ConsistencyChecks) updateSTR(requestType int, msg *Response) error { // verifySTR checks whether the received STR is the same with // the SavedSTR using reflect.DeepEqual(). -func (cc *ConsistencyChecks) verifySTR(str *m.SignedTreeRoot) error { +func (cc *ConsistencyChecks) verifySTR(str *DirSTR) error { if reflect.DeepEqual(cc.SavedSTR, str) { return nil } @@ -143,7 +143,7 @@ func (cc *ConsistencyChecks) verifySTR(str *m.SignedTreeRoot) error { // It uses the pinned signing key in cc // to verify the STR's signature and should not verify // the hash chain using the STR stored in cc. -func (cc *ConsistencyChecks) verifySTRConsistency(savedSTR, str *m.SignedTreeRoot) error { +func (cc *ConsistencyChecks) verifySTRConsistency(savedSTR, str *DirSTR) error { // verify STR's signature if !cc.signKey.Verify(str.Serialize(), str.Signature) { return CheckBadSignature @@ -151,7 +151,6 @@ func (cc *ConsistencyChecks) verifySTRConsistency(savedSTR, str *m.SignedTreeRoo if str.VerifyHashChain(savedSTR) { return nil } - // TODO: verify the directory's policies as well. See #115 return CheckBadSTR } @@ -215,12 +214,9 @@ func (cc *ConsistencyChecks) verifyKeyLookup(msg *Response, return CheckPassed } -func verifyAuthPath(uname string, key []byte, - ap *m.AuthenticationPath, - str *m.SignedTreeRoot) error { - +func verifyAuthPath(uname string, key []byte, ap *m.AuthenticationPath, str *DirSTR) error { // verify VRF Index - vrfKey := GetPolicies(str).VrfPublicKey + vrfKey := str.Policies.VrfPublicKey if !vrfKey.Verify([]byte(uname), ap.LookupIndex, ap.VrfProof) { return CheckBadVRFProof } @@ -290,8 +286,7 @@ func (cc *ConsistencyChecks) updateTBs(requestType int, msg *Response, // verifyFulfilledPromise verifies issued TBs were inserted // in the directory as promised. -func (cc *ConsistencyChecks) verifyFulfilledPromise(uname string, - str *m.SignedTreeRoot, +func (cc *ConsistencyChecks) verifyFulfilledPromise(uname string, str *DirSTR, ap *m.AuthenticationPath) error { // FIXME: Which epoch did this lookup happen in? if tb, ok := cc.TBs[uname]; ok { diff --git a/protocol/consistencychecks_test.go b/protocol/consistencychecks_test.go index 815da4f..81ac271 100644 --- a/protocol/consistencychecks_test.go +++ b/protocol/consistencychecks_test.go @@ -32,16 +32,21 @@ func lookupAndVerify(d *ConiksDirectory, cc *ConsistencyChecks, func TestVerifyWithError(t *testing.T) { d, pk := NewTestDirectory(t, true) + str := d.LatestSTR() // modify the pinning STR so that the consistency check should fail. - str := *(d.LatestSTR()) - str.Signature = append([]byte{}, str.Signature...) - str.Signature[0]++ + str2 := *str.SignedTreeRoot + str2.Signature = append([]byte{}, str.Signature...) + str2.Signature[0]++ + str.SignedTreeRoot = &str2 - cc := NewCC(&str, true, pk) + cc := NewCC(str, true, pk) - if e1, e2 := registerAndVerify(d, cc, alice, key); e1 != ReqSuccess || e2 != CheckBadSTR { + e1, e2 := registerAndVerify(d, cc, alice, key) + if e1 != ReqSuccess { t.Error("Expect", ReqSuccess, "got", e1) + } + if e2 != CheckBadSTR { t.Error("Expect", CheckBadSTR, "got", e2) } } diff --git a/protocol/directory.go b/protocol/directory.go index fd8f81f..1bb053b 100644 --- a/protocol/directory.go +++ b/protocol/directory.go @@ -87,8 +87,8 @@ func (d *ConiksDirectory) EpochDeadline() Timestamp { } // LatestSTR returns this ConiksDirectory's latest STR. -func (d *ConiksDirectory) LatestSTR() *merkletree.SignedTreeRoot { - return d.pad.LatestSTR() +func (d *ConiksDirectory) LatestSTR() *DirSTR { + return NewDirSTR(d.pad.LatestSTR()) } // NewTB creates a new temporary binding for the given name-to-key mapping. @@ -252,7 +252,7 @@ func (d *ConiksDirectory) KeyLookupInEpoch(req *KeyLookupInEpochRequest) ( ErrMalformedClientMessage } - var strs []*merkletree.SignedTreeRoot + var strs []*DirSTR startEp := req.Epoch endEp := d.LatestSTR().Epoch @@ -261,7 +261,7 @@ func (d *ConiksDirectory) KeyLookupInEpoch(req *KeyLookupInEpochRequest) ( return NewErrorResponse(ErrDirectory), ErrDirectory } for ep := startEp; ep <= endEp; ep++ { - str := d.pad.GetSTR(ep) + str := NewDirSTR(d.pad.GetSTR(ep)) strs = append(strs, str) } @@ -302,7 +302,7 @@ func (d *ConiksDirectory) Monitor(req *MonitoringRequest) ( ErrMalformedClientMessage } - var strs []*merkletree.SignedTreeRoot + var strs []*DirSTR var aps []*merkletree.AuthenticationPath startEp := req.StartEpoch endEp := req.EndEpoch @@ -315,7 +315,7 @@ func (d *ConiksDirectory) Monitor(req *MonitoringRequest) ( return NewErrorResponse(ErrDirectory), ErrDirectory } aps = append(aps, ap) - str := d.pad.GetSTR(ep) + str := NewDirSTR(d.pad.GetSTR(ep)) strs = append(strs, str) } diff --git a/protocol/directory_test.go b/protocol/directory_test.go index 7930ac0..2571ca9 100644 --- a/protocol/directory_test.go +++ b/protocol/directory_test.go @@ -255,7 +255,7 @@ func TestMonitoringBadStartEpoch(t *testing.T) { func TestPoliciesChanges(t *testing.T) { d, _ := NewTestDirectory(t, true) - if p := GetPolicies(d.LatestSTR()).EpochDeadline; p != 1 { + if p := d.LatestSTR().Policies.EpochDeadline; p != 1 { t.Fatal("Unexpected policies", "want", 1, "got", p) } @@ -263,13 +263,13 @@ func TestPoliciesChanges(t *testing.T) { d.SetPolicies(2) d.Update() // expect the policies doesn't change yet - if p := GetPolicies(d.LatestSTR()).EpochDeadline; p != 1 { + if p := d.LatestSTR().Policies.EpochDeadline; p != 1 { t.Fatal("Unexpected policies", "want", 1, "got", p) } d.Update() // expect the new policies - if p := GetPolicies(d.LatestSTR()).EpochDeadline; p != 2 { + if p := d.LatestSTR().Policies.EpochDeadline; p != 2 { t.Fatal("Unexpected policies", "want", 2, "got", p) } p0 := GetPolicies(d.pad.GetSTR(0)).EpochDeadline diff --git a/protocol/message.go b/protocol/message.go index f7a7d8d..daed201 100644 --- a/protocol/message.go +++ b/protocol/message.go @@ -110,7 +110,7 @@ type DirectoryResponse interface{} // type upon a RegistrationRequest or a KeyLookupRequest. type DirectoryProof struct { AP *m.AuthenticationPath - STR *m.SignedTreeRoot + STR *DirSTR TB *TemporaryBinding `json:",omitempty"` } @@ -121,7 +121,7 @@ type DirectoryProof struct { // MonitoringRequest. type DirectoryProofs struct { AP []*m.AuthenticationPath - STR []*m.SignedTreeRoot + STR []*DirSTR } // NewErrorResponse creates a new response message indicating the error @@ -143,7 +143,7 @@ var _ DirectoryResponse = (*DirectoryProofs)(nil) // // See directory.Register() for details on the contents of the created // DirectoryProof. -func NewRegistrationProof(ap *m.AuthenticationPath, str *m.SignedTreeRoot, +func NewRegistrationProof(ap *m.AuthenticationPath, str *DirSTR, tb *TemporaryBinding, e ErrorCode) (*Response, ErrorCode) { return &Response{ Error: e, @@ -164,7 +164,7 @@ func NewRegistrationProof(ap *m.AuthenticationPath, str *m.SignedTreeRoot, // // See directory.KeyLookup() for details on the contents of the created // DirectoryProof. -func NewKeyLookupProof(ap *m.AuthenticationPath, str *m.SignedTreeRoot, +func NewKeyLookupProof(ap *m.AuthenticationPath, str *DirSTR, tb *TemporaryBinding, e ErrorCode) (*Response, ErrorCode) { return &Response{ Error: e, @@ -186,7 +186,7 @@ func NewKeyLookupProof(ap *m.AuthenticationPath, str *m.SignedTreeRoot, // See directory.KeyLookupInEpoch() for details on the contents of the // created DirectoryProofs. func NewKeyLookupInEpochProof(ap *m.AuthenticationPath, - str []*m.SignedTreeRoot, e ErrorCode) (*Response, ErrorCode) { + str []*DirSTR, e ErrorCode) (*Response, ErrorCode) { aps := append([]*m.AuthenticationPath{}, ap) return &Response{ Error: e, @@ -206,7 +206,7 @@ func NewKeyLookupInEpochProof(ap *m.AuthenticationPath, // See directory.Monitor() for details on the contents of the created // DirectoryProofs. func NewMonitoringProof(ap []*m.AuthenticationPath, - str []*m.SignedTreeRoot) (*Response, ErrorCode) { + str []*DirSTR) (*Response, ErrorCode) { return &Response{ Error: ReqSuccess, DirectoryResponse: &DirectoryProofs{ diff --git a/protocol/str.go b/protocol/str.go new file mode 100644 index 0000000..bd6c8e3 --- /dev/null +++ b/protocol/str.go @@ -0,0 +1,23 @@ +package protocol + +import "github.com/coniks-sys/coniks-go/merkletree" + +// DirSTR disambiguates merkletree.SignedTreeRoot's AssocData interface, +// for the purpose of exporting and unmarshalling. +type DirSTR struct { + *merkletree.SignedTreeRoot + Policies *Policies +} + +// NewDirSTR constructs a new DirSTR from a merkletree.SignedTreeRoot +func NewDirSTR(str *merkletree.SignedTreeRoot) *DirSTR { + return &DirSTR{ + str, + str.Ad.(*Policies), + } +} + +// VerifyHashChain wraps merkletree.SignedTreeRoot.VerifyHashChain +func (str *DirSTR) VerifyHashChain(savedSTR *DirSTR) bool { + return str.SignedTreeRoot.VerifyHashChain(savedSTR.SignedTreeRoot) +} diff --git a/protocol/str_test.go b/protocol/str_test.go new file mode 100644 index 0000000..3ecbddd --- /dev/null +++ b/protocol/str_test.go @@ -0,0 +1,23 @@ +package protocol + +import "testing" + +func TestVerifyHashChain(t *testing.T) { + var N uint64 = 100 + d, pk := NewTestDirectory(t, true) + savedSTR := d.LatestSTR() + for i := uint64(1); i < N; i++ { + d.Update() + str := d.LatestSTR() + if i != str.Epoch { + t.Fatal("Epochs aren't increasing.") + } + if !pk.Verify(str.Serialize(), str.Signature) { + t.Fatal("Invalid STR signature at epoch", i) + } + if !str.VerifyHashChain(savedSTR) { + t.Fatal("Spurious STR at epoch", i) + } + savedSTR = str + } +} From 6827a2177cc4faa2edd5b85279a6a0707580dfe9 Mon Sep 17 00:00:00 2001 From: Vu Quoc Huy Date: Wed, 21 Dec 2016 21:37:43 +0700 Subject: [PATCH 2/7] Enable client debugging mode: - Add command to enable/disable timestamp printing - Add debug flag and "q" command to exit --- client/coniksclient/internal/cmd/common.go | 6 ++- client/coniksclient/internal/cmd/run.go | 46 ++++++++++++++++------ 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/client/coniksclient/internal/cmd/common.go b/client/coniksclient/internal/cmd/common.go index 7548eb7..df1bc33 100644 --- a/client/coniksclient/internal/cmd/common.go +++ b/client/coniksclient/internal/cmd/common.go @@ -3,6 +3,7 @@ package cmd import ( "fmt" "os" + "time" "github.com/coniks-sys/coniks-go/client" "github.com/spf13/cobra" @@ -38,6 +39,9 @@ func loadConfigOrExit(cmd *cobra.Command) *client.Config { } // append "\r\n" to msg and then write to terminal in raw mode. -func writeLineInRawMode(term *terminal.Terminal, msg string) { +func writeLineInRawMode(term *terminal.Terminal, msg string, printTimestamp bool) { + if printTimestamp { + term.Write([]byte("<" + time.Now().Format("15:04:05.999999999") + "> ")) + } term.Write([]byte(msg + "\r\n")) } diff --git a/client/coniksclient/internal/cmd/run.go b/client/coniksclient/internal/cmd/run.go index eb240bf..7f3b319 100644 --- a/client/coniksclient/internal/cmd/run.go +++ b/client/coniksclient/internal/cmd/run.go @@ -4,6 +4,7 @@ import ( "log" "net/url" "os" + "strconv" "strings" "github.com/coniks-sys/coniks-go/client" @@ -17,9 +18,13 @@ const help = "- register [name] [key]:\r\n" + " Register a new name-to-key binding on the CONIKS-server.\r\n" + "- lookup [name]:\r\n" + " Lookup the key of some known contact or your own bindings.\r\n" + + "- enable timestamp:\r\n" + + " Print timestamp of format <15:04:05.999999999> along with the result.\r\n" + + "- disable timestamp:\r\n" + + " Disable timestamp printing.\r\n" + "- help:\r\n" + " Display this message.\r\n" + - "- exit:\r\n" + + "- exit, q:\r\n" + " Close the REPL and exit the client." var runCmd = &cobra.Command{ @@ -35,9 +40,11 @@ func init() { RootCmd.AddCommand(runCmd) runCmd.Flags().StringP("config", "c", "config.toml", "Config file for the client (contains the server's initial public key etc).") + runCmd.Flags().BoolP("debug", "d", false, "Turn on debugging mode") } func run(cmd *cobra.Command) { + isDebugging, _ := strconv.ParseBool(cmd.Flag("debug").Value.String()) conf := loadConfigOrExit(cmd) cc := p.NewCC(nil, true, conf.SigningPubKey) @@ -50,41 +57,54 @@ func run(cmd *cobra.Command) { for { line, err := term.ReadLine() if err != nil { - writeLineInRawMode(term, err.Error()) + writeLineInRawMode(term, err.Error(), isDebugging) return } args := strings.Fields(line) if len(args) < 1 { - writeLineInRawMode(term, `[!] Type "help" for more information.`) + writeLineInRawMode(term, `[!] Type "help" for more information.`, isDebugging) continue } cmd := args[0] switch cmd { - case "exit": - writeLineInRawMode(term, "[+] See ya.") + case "exit", "q": + writeLineInRawMode(term, "[+] See ya.", isDebugging) return case "help": - writeLineInRawMode(term, help) - continue + writeLineInRawMode(term, help, false) // turn off debugging mode for this command + case "enable", "disable": + if len(args) != 2 { + writeLineInRawMode(term, "[!] Unrecognized command: "+line, isDebugging) + continue + } + switch args[1] { + case "timestamp": + if cmd == "enable" { + isDebugging = true + } else { + isDebugging = false + } + default: + writeLineInRawMode(term, "[!] Unrecognized command: "+line, isDebugging) + } case "register": if len(args) != 3 { - writeLineInRawMode(term, "[!] Incorrect number of args to register.") + writeLineInRawMode(term, "[!] Incorrect number of args to register.", isDebugging) continue } msg := register(cc, conf, args[1], args[2]) - writeLineInRawMode(term, "[+] "+msg) + writeLineInRawMode(term, "[+] "+msg, isDebugging) case "lookup": if len(args) != 2 { - writeLineInRawMode(term, "[!] Incorrect number of args to lookup.") + writeLineInRawMode(term, "[!] Incorrect number of args to lookup.", isDebugging) continue } msg := keyLookup(cc, conf, args[1]) - writeLineInRawMode(term, "[+] "+msg) + writeLineInRawMode(term, "[+] "+msg, isDebugging) default: - writeLineInRawMode(term, "[!] Unrecognized command: "+cmd) - continue + writeLineInRawMode(term, "[!] Unrecognized command: "+cmd, isDebugging) } } } From 85b16d0919981cd47cd4faf5a4ae5864db49ab12 Mon Sep 17 00:00:00 2001 From: Vu Quoc Huy Date: Fri, 23 Dec 2016 13:13:31 +0700 Subject: [PATCH 3/7] Fix mismatch request type --- client/coniksclient/internal/cmd/run.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/coniksclient/internal/cmd/run.go b/client/coniksclient/internal/cmd/run.go index 7f3b319..23e816d 100644 --- a/client/coniksclient/internal/cmd/run.go +++ b/client/coniksclient/internal/cmd/run.go @@ -190,7 +190,7 @@ func keyLookup(cc *p.ConsistencyChecks, conf *client.Config, name string) string return ("Invalid config!") } - response := client.UnmarshalResponse(p.RegistrationType, res) + response := client.UnmarshalResponse(p.KeyLookupType, res) if key, ok := cc.Bindings[name]; ok { err = cc.HandleResponse(p.KeyLookupType, response, name, []byte(key)) } else { From 4244484f55d87d2a225db64005a0ff783ca9ca8b Mon Sep 17 00:00:00 2001 From: Vu Quoc Huy Date: Fri, 23 Dec 2016 10:50:39 +0700 Subject: [PATCH 4/7] Hotfix: STR.Ad unmarshalling --- client/encoding.go | 4 ++++ client/encoding_test.go | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/client/encoding.go b/client/encoding.go index ab2a5c8..6f3e6ca 100644 --- a/client/encoding.go +++ b/client/encoding.go @@ -42,6 +42,7 @@ func UnmarshalResponse(t int, msg []byte) *p.Response { Error: p.ErrMalformedDirectoryMessage, } } + response.STR.Ad = response.STR.Policies return &p.Response{ Error: res.Error, DirectoryResponse: response, @@ -53,6 +54,9 @@ func UnmarshalResponse(t int, msg []byte) *p.Response { Error: p.ErrMalformedDirectoryMessage, } } + for i := 0; i < len(response.STR); i++ { + response.STR[i].Ad = response.STR[i].Policies + } return &p.Response{ Error: res.Error, DirectoryResponse: response, diff --git a/client/encoding_test.go b/client/encoding_test.go index 6f778f1..0d67934 100644 --- a/client/encoding_test.go +++ b/client/encoding_test.go @@ -1,9 +1,11 @@ package client import ( + "bytes" "encoding/json" "testing" + "github.com/coniks-sys/coniks-go/keyserver" "github.com/coniks-sys/coniks-go/protocol" ) @@ -32,3 +34,16 @@ func TestUnmarshalMalformedErrorResponse(t *testing.T) { "got", res.Error) } } + +func TestUnmarshalSampleMessage(t *testing.T) { + d, _ := protocol.NewTestDirectory(t, true) + res, _ := d.Register(&protocol.RegistrationRequest{ + Username: "alice", + Key: []byte("key")}) + msg, _ := keyserver.MarshalResponse(res) + response := UnmarshalResponse(protocol.RegistrationType, []byte(msg)) + str := response.DirectoryResponse.(*protocol.DirectoryProof).STR + if str.Ad == nil || !bytes.Equal(str.Ad.Serialize(), str.Policies.Serialize()) { + t.Error("Cannot unmarshal Associate Data properly") + } +} From 656194102fc9920fa7793f76c36c814087a2730c Mon Sep 17 00:00:00 2001 From: Arlo Breault Date: Fri, 23 Dec 2016 08:06:30 -0800 Subject: [PATCH 5/7] Fill in AssocData while unmarshalling --- client/encoding.go | 4 ---- protocol/str.go | 21 ++++++++++++++++++++- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/client/encoding.go b/client/encoding.go index 6f3e6ca..ab2a5c8 100644 --- a/client/encoding.go +++ b/client/encoding.go @@ -42,7 +42,6 @@ func UnmarshalResponse(t int, msg []byte) *p.Response { Error: p.ErrMalformedDirectoryMessage, } } - response.STR.Ad = response.STR.Policies return &p.Response{ Error: res.Error, DirectoryResponse: response, @@ -54,9 +53,6 @@ func UnmarshalResponse(t int, msg []byte) *p.Response { Error: p.ErrMalformedDirectoryMessage, } } - for i := 0; i < len(response.STR); i++ { - response.STR[i].Ad = response.STR[i].Policies - } return &p.Response{ Error: res.Error, DirectoryResponse: response, diff --git a/protocol/str.go b/protocol/str.go index bd6c8e3..65ccd34 100644 --- a/protocol/str.go +++ b/protocol/str.go @@ -1,6 +1,10 @@ package protocol -import "github.com/coniks-sys/coniks-go/merkletree" +import ( + "encoding/json" + + "github.com/coniks-sys/coniks-go/merkletree" +) // DirSTR disambiguates merkletree.SignedTreeRoot's AssocData interface, // for the purpose of exporting and unmarshalling. @@ -21,3 +25,18 @@ func NewDirSTR(str *merkletree.SignedTreeRoot) *DirSTR { func (str *DirSTR) VerifyHashChain(savedSTR *DirSTR) bool { return str.SignedTreeRoot.VerifyHashChain(savedSTR.SignedTreeRoot) } + +// UnmarshalJSON fills in the unexported Ad interface from the underlying +// merkletree.SignedTreeRoot. This is necessary since, for now, Serialize +// and VerifyHashChain dispatch to methods which dereference it. +func (str *DirSTR) UnmarshalJSON(m []byte) error { + // Use an alias to avoid an infinite loop + type DirSTR2 DirSTR + str2 := &DirSTR2{} + if err := json.Unmarshal(m, str2); err != nil { + return err + } + str2.Ad = str2.Policies + *str = DirSTR(*str2) + return nil +} From 0bedfc6e83b710377aee19011a90f48e57c1584d Mon Sep 17 00:00:00 2001 From: Arlo Breault Date: Wed, 18 Jan 2017 16:24:37 -0800 Subject: [PATCH 6/7] Run `go vet` in CI --- .travis.yml | 1 + merkletree/merkletree.go | 13 ++++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 861ba01..a884f60 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,7 @@ env: script: - test -z "$(go fmt ./...)" + - go vet ./... - ./test_coverage.sh after_success: diff --git a/merkletree/merkletree.go b/merkletree/merkletree.go index d20ee3d..8c054b0 100644 --- a/merkletree/merkletree.go +++ b/merkletree/merkletree.go @@ -91,11 +91,14 @@ func (m *MerkleTree) Get(lookupIndex []byte) *AuthenticationPath { case *userLeafNode: pNode := nodePointer.(*userLeafNode) authPath.Leaf = &ProofNode{ - Level: pNode.level, - Index: pNode.index, - Value: pNode.value, - IsEmpty: false, - Commitment: &crypto.Commit{pNode.commitment.Salt, pNode.commitment.Value}, + Level: pNode.level, + Index: pNode.index, + Value: pNode.value, + IsEmpty: false, + Commitment: &crypto.Commit{ + Salt: pNode.commitment.Salt, + Value: pNode.commitment.Value, + }, } if bytes.Equal(nodePointer.(*userLeafNode).index, lookupIndex) { return authPath From deb014011bc7b0eb79b2b9492c814b031742fe3e Mon Sep 17 00:00:00 2001 From: c633 Date: Sun, 25 Dec 2016 15:35:56 +0700 Subject: [PATCH 7/7] Override STR.SerializeWithAd of the STR struct for signing --- client/encoding_test.go | 2 +- merkletree/str.go | 15 ++++++++++++--- merkletree/str_test.go | 2 +- protocol/str.go | 26 ++++++-------------------- 4 files changed, 20 insertions(+), 25 deletions(-) diff --git a/client/encoding_test.go b/client/encoding_test.go index 0d67934..4abc9c7 100644 --- a/client/encoding_test.go +++ b/client/encoding_test.go @@ -43,7 +43,7 @@ func TestUnmarshalSampleMessage(t *testing.T) { msg, _ := keyserver.MarshalResponse(res) response := UnmarshalResponse(protocol.RegistrationType, []byte(msg)) str := response.DirectoryResponse.(*protocol.DirectoryProof).STR - if str.Ad == nil || !bytes.Equal(str.Ad.Serialize(), str.Policies.Serialize()) { + if !bytes.Equal(d.LatestSTR().Serialize(), str.Serialize()) { t.Error("Cannot unmarshal Associate Data properly") } } diff --git a/merkletree/str.go b/merkletree/str.go index 26d5982..a640abc 100644 --- a/merkletree/str.go +++ b/merkletree/str.go @@ -51,9 +51,19 @@ func NewSTR(key sign.PrivateKey, ad AssocData, m *MerkleTree, epoch uint64, prev return str } -// Serialize serializes the signed tree root into -// a specified format for signing. +// Serialize serializes the signed tree root +// and its associated data into a specified format for signing. +// One should use this function for signing as well as +// verifying the signature. +// Any composition struct of SignedTreeRoot with +// a specific AssocData should override this method. func (str *SignedTreeRoot) Serialize() []byte { + return append(str.SerializeInternal(), str.Ad.Serialize()...) +} + +// SerializeInternal serializes the signed tree root into +// a specified format. +func (str *SignedTreeRoot) SerializeInternal() []byte { var strBytes []byte strBytes = append(strBytes, utils.ULongToBytes(str.Epoch)...) // t - epoch number if str.Epoch > 0 { @@ -61,7 +71,6 @@ func (str *SignedTreeRoot) Serialize() []byte { } strBytes = append(strBytes, str.TreeHash...) // root strBytes = append(strBytes, str.PreviousSTRHash...) // previous STR hash - strBytes = append(strBytes, str.Ad.Serialize()...) return strBytes } diff --git a/merkletree/str_test.go b/merkletree/str_test.go index dbfff47..82fb88d 100644 --- a/merkletree/str_test.go +++ b/merkletree/str_test.go @@ -7,7 +7,7 @@ func TestVerifyHashChain(t *testing.T) { keyPrefix := "key" valuePrefix := []byte("value") - pad, err := NewPAD(TestAd{""}, signKey, vrfPrivKey1, 10) + pad, err := NewPAD(TestAd{"abc"}, signKey, vrfPrivKey1, 10) if err != nil { t.Fatal(err) } diff --git a/protocol/str.go b/protocol/str.go index 65ccd34..db92f96 100644 --- a/protocol/str.go +++ b/protocol/str.go @@ -1,10 +1,6 @@ package protocol -import ( - "encoding/json" - - "github.com/coniks-sys/coniks-go/merkletree" -) +import "github.com/coniks-sys/coniks-go/merkletree" // DirSTR disambiguates merkletree.SignedTreeRoot's AssocData interface, // for the purpose of exporting and unmarshalling. @@ -21,22 +17,12 @@ func NewDirSTR(str *merkletree.SignedTreeRoot) *DirSTR { } } +// Serialize overrides merkletree.SignedTreeRoot.Serialize +func (str *DirSTR) Serialize() []byte { + return append(str.SerializeInternal(), str.Policies.Serialize()...) +} + // VerifyHashChain wraps merkletree.SignedTreeRoot.VerifyHashChain func (str *DirSTR) VerifyHashChain(savedSTR *DirSTR) bool { return str.SignedTreeRoot.VerifyHashChain(savedSTR.SignedTreeRoot) } - -// UnmarshalJSON fills in the unexported Ad interface from the underlying -// merkletree.SignedTreeRoot. This is necessary since, for now, Serialize -// and VerifyHashChain dispatch to methods which dereference it. -func (str *DirSTR) UnmarshalJSON(m []byte) error { - // Use an alias to avoid an infinite loop - type DirSTR2 DirSTR - str2 := &DirSTR2{} - if err := json.Unmarshal(m, str2); err != nil { - return err - } - str2.Ad = str2.Policies - *str = DirSTR(*str2) - return nil -}