Skip to content

Commit f230638

Browse files
authored
Use bytes.Equal for inclusion proof root hash comparison (#2861)
VerifyCheckpointSignature compared the inclusion proof root hash to the signed tree head with bytes.EqualFold, which folds ASCII case, so two hashes differing only by letter case compared equal. The other root hash comparisons in this package use bytes.Equal. Signed-off-by: kanywst <niwatakuma@icloud.com>
1 parent 7472268 commit f230638

2 files changed

Lines changed: 37 additions & 1 deletion

File tree

pkg/verify/verify.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ func VerifyCheckpointSignature(e *models.LogEntryAnon, verifier signature.Verifi
126126
return errors.New("decoding inclusion proof root has")
127127
}
128128

129-
if !bytes.EqualFold(rootHash, sth.Hash) {
129+
if !bytes.Equal(rootHash, sth.Hash) {
130130
return fmt.Errorf("proof root hash does not match signed tree head, expected %s got %s",
131131
*e.Verification.InclusionProof.RootHash,
132132
hex.EncodeToString(sth.Hash))

pkg/verify/verify_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,3 +340,39 @@ func TestCheckpoint(t *testing.T) {
340340
})
341341
}
342342
}
343+
344+
func TestCheckpointRootHashCaseFolding(t *testing.T) {
345+
signer, _, err := signature.NewDefaultECDSASignerVerifier()
346+
if err != nil {
347+
t.Fatal(err)
348+
}
349+
350+
var rootHash [32]byte
351+
for i := range rootHash {
352+
rootHash[i] = byte(i) + 1
353+
}
354+
rootHash[0] = 'A'
355+
356+
scBytes, err := util.CreateAndSignCheckpoint(context.Background(), "rekor.localhost", 123, 42, rootHash[:], signer)
357+
if err != nil {
358+
t.Fatal(err)
359+
}
360+
361+
// Same bytes except an ASCII letter in different case: not equal, but equal
362+
// under case folding.
363+
mismatch := rootHash
364+
mismatch[0] = 'a'
365+
366+
e := models.LogEntryAnon{
367+
Verification: &models.LogEntryAnonVerification{
368+
InclusionProof: &models.InclusionProof{
369+
RootHash: conv.Pointer(hex.EncodeToString(mismatch[:])),
370+
Checkpoint: conv.Pointer(string(scBytes)),
371+
},
372+
},
373+
}
374+
375+
if err := VerifyCheckpointSignature(&e, signer); err == nil {
376+
t.Fatal("VerifyCheckpointSignature accepted a root hash that does not match the signed tree head")
377+
}
378+
}

0 commit comments

Comments
 (0)