diff --git a/client/coniksclient/internal/cmd/register.go b/client/coniksclient/internal/cmd/register.go index 762d3bc..067a0fa 100644 --- a/client/coniksclient/internal/cmd/register.go +++ b/client/coniksclient/internal/cmd/register.go @@ -75,14 +75,14 @@ Example call: case p.CheckBindingsDiffer: switch response.Error { case p.ReqNameExisted: - fmt.Println(`Are you trying to update your binding? Unfortunately, KeyChange hasn't been supported yet.`) + fmt.Println(`Are you trying to update your binding? Unfortunately, KeyChange isn't supported yet.`) case p.ReqSuccess: - fmt.Println("Oops! Probably the server is trying to sneak in some other key.") + fmt.Println("Oops! The server snuck in some other key.") recvKey, err := response.GetKey() if err != nil { fmt.Println("Cannot get the key from the response, error: " + err.Error()) } - fmt.Println("You got [" + string(recvKey) + "] instead of [" + string(key) + "]") + fmt.Println("[" + string(recvKey) + "] was registered instead of [" + string(key) + "]") } default: fmt.Println("Error: " + err.Error()) diff --git a/merkletree/proof.go b/merkletree/proof.go index 9471f03..49e2564 100644 --- a/merkletree/proof.go +++ b/merkletree/proof.go @@ -80,21 +80,25 @@ func (ap *AuthenticationPath) authPathHash() []byte { return hash } -// VerifyBinding verifies both the value and the commitment -// of the proof node of the authentication path. -// -// This should be called only when ap is a proof of inclusion. +// VerifyBinding verifies the value of the proof node +// of the authentication path. It also verifies the commitment +// of the proof node if ap is a proof of inclusion. func (ap *AuthenticationPath) VerifyBinding(key, value []byte) bool { - return bytes.Equal(ap.Leaf.Value, value) && - ap.Leaf.Commitment.Verify(key, value) + return (ap.ProofType() == ProofOfAbsence && ap.Leaf.Value == nil) || + (bytes.Equal(ap.Leaf.Value, value) && ap.Leaf.Commitment.Verify(key, value)) } -// VerifyIndex checks if the private index of the proof node and -// the lookup index match in the first l bits with l is the Level -// of the proof node. +// VerifyIndex verifies the private index of the proof node. +// +// If the proof is a proof of absence, it checks if the index +// of the proof node and the lookup index match in the first +// l bits with l is the Level of the proof node. // -// This should be called only when ap is a proof of absence. +// If the proof is a proof of inclusion, it returns true immediately. func (ap *AuthenticationPath) VerifyIndex() bool { + if ap.ProofType() == ProofOfInclusion { + return true + } // Check if i and j match in the first l bits indexBits := utils.ToBits(ap.Leaf.Index) lookupIndexBits := utils.ToBits(ap.LookupIndex) @@ -114,19 +118,6 @@ func (ap *AuthenticationPath) VerifySTR(treeHash []byte) bool { return bytes.Equal(treeHash, ap.authPathHash()) } -// Verify combines VerifyBinding(), VerifyIndex(), and VerifySTR(), -// and abstracts away the detail of the failure. -// This should be called after the VRF index is verified successfully. -func (ap *AuthenticationPath) Verify(key, value, treeHash []byte) bool { - switch { - case ap.ProofType() == ProofOfAbsence && ap.VerifyIndex(), - ap.ProofType() == ProofOfInclusion && ap.VerifyBinding(key, value): - return ap.VerifySTR(treeHash) - default: - return false - } -} - func (ap *AuthenticationPath) ProofType() ProofType { if ap.proofType == undeterminedProof { if bytes.Equal(ap.LookupIndex, ap.Leaf.Index) { diff --git a/merkletree/proof_test.go b/merkletree/proof_test.go index b71aa9e..8908478 100644 --- a/merkletree/proof_test.go +++ b/merkletree/proof_test.go @@ -7,6 +7,16 @@ import ( "github.com/coniks-sys/coniks-go/utils" ) +func verifyAuthPath(ap *AuthenticationPath, key, value []byte, treehash []byte) bool { + if !ap.VerifyIndex() { + return false + } + if !ap.VerifyBinding(key, value) { + return false + } + return ap.VerifySTR(treehash) +} + func TestVerifyProof(t *testing.T) { m, err := NewMerkleTree() if err != nil { @@ -63,7 +73,7 @@ func TestVerifyProof(t *testing.T) { t.Fatal("Expect a proof of inclusion") } // verify auth path - if !proof.Verify([]byte(key3), val3, m.hash) { + if !verifyAuthPath(proof, []byte(key3), val3, m.hash) { t.Error("Proof of inclusion verification failed.") } @@ -78,7 +88,7 @@ func TestVerifyProof(t *testing.T) { !bytes.Equal(vrfPrivKey1.Compute([]byte("123")), proof.LookupIndex) { t.Fatal("Expect a proof of absence") } - if !proof.Verify([]byte("123"), nil, m.hash) { + if !verifyAuthPath(proof, []byte("123"), nil, m.hash) { t.Error("Proof of absence verification failed.") } } @@ -111,7 +121,7 @@ func TestVerifyProofSamePrefix(t *testing.T) { utils.ToBytes(utils.ToBits(absentIndex)[:proof.Leaf.Level])) { t.Fatal("Expect these indices share the same prefix in the first bit") } - if !proof.Verify([]byte("a"), nil, m.hash) { + if !verifyAuthPath(proof, []byte("a"), nil, m.hash) { t.Error("Proof of absence verification failed.") } @@ -128,7 +138,7 @@ func TestVerifyProofSamePrefix(t *testing.T) { t.Fatal("Expect a proof of inclusion") } // step 2. verify auth path - if !proof.Verify([]byte(key1), val1, m.hash) { + if !verifyAuthPath(proof, []byte(key1), val1, m.hash) { t.Error("Proof of inclusion verification failed.") } } diff --git a/protocol/consistencychecks.go b/protocol/consistencychecks.go index 3265235..25a56d3 100644 --- a/protocol/consistencychecks.go +++ b/protocol/consistencychecks.go @@ -218,25 +218,16 @@ func verifyAuthPath(uname string, key []byte, return CheckBadVRFProof } - if key == nil { - // key is nil when the user does lookup for the first time. - // Accept the received key as TOFU - key = ap.Leaf.Value + if !ap.VerifyIndex() { + return CheckBadLookupIndex } - - if ap.ProofType() == m.ProofOfAbsence { - if !ap.VerifyIndex() { - return CheckBadLookupIndex - } - } else { - if !ap.VerifyBinding([]byte(uname), key) { - return CheckBindingsDiffer - } + if key != nil && !ap.VerifyBinding([]byte(uname), key) { + return CheckBindingsDiffer } - if ap.VerifySTR(str.TreeHash) { - return nil + if !ap.VerifySTR(str.TreeHash) { + return CheckBadAuthPath } - return CheckBadAuthPath + return nil } func (cc *ConsistencyChecks) updateTBs(requestType int, msg *Response,