Drop the MerkleTreeBuilder return value from VerifyConsistencyProof
This commit is contained in:
parent
ef00e22ec1
commit
0c751f0294
32
auditing.go
32
auditing.go
|
@ -24,18 +24,17 @@ func reverseHashes(hashes []ct.MerkleTreeNode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: drop the MerkleTreeBuilder return value
|
func VerifyConsistencyProof(proof ct.ConsistencyProof, first *ct.SignedTreeHead, second *ct.SignedTreeHead) bool {
|
||||||
func VerifyConsistencyProof(proof ct.ConsistencyProof, first *ct.SignedTreeHead, second *ct.SignedTreeHead) (bool, *MerkleTreeBuilder) {
|
|
||||||
// TODO: make sure every hash in proof is right length? otherwise input to hashChildren is ambiguous
|
// TODO: make sure every hash in proof is right length? otherwise input to hashChildren is ambiguous
|
||||||
if second.TreeSize < first.TreeSize {
|
if second.TreeSize < first.TreeSize {
|
||||||
// Can't be consistent if tree got smaller
|
// Can't be consistent if tree got smaller
|
||||||
return false, nil
|
return false
|
||||||
}
|
}
|
||||||
if first.TreeSize == second.TreeSize {
|
if first.TreeSize == second.TreeSize {
|
||||||
if !(bytes.Equal(first.SHA256RootHash[:], second.SHA256RootHash[:]) && len(proof) == 0) {
|
if !(bytes.Equal(first.SHA256RootHash[:], second.SHA256RootHash[:]) && len(proof) == 0) {
|
||||||
return false, nil
|
return false
|
||||||
}
|
}
|
||||||
return true, &MerkleTreeBuilder{stack: []ct.MerkleTreeNode{first.SHA256RootHash[:]}, numLeaves: 1}
|
return true
|
||||||
}
|
}
|
||||||
if first.TreeSize == 0 {
|
if first.TreeSize == 0 {
|
||||||
// The purpose of the consistency proof is to ensure the append-only
|
// The purpose of the consistency proof is to ensure the append-only
|
||||||
|
@ -43,9 +42,9 @@ func VerifyConsistencyProof(proof ct.ConsistencyProof, first *ct.SignedTreeHead,
|
||||||
// second tree. If the first tree is empty, then it's trivially a prefix
|
// second tree. If the first tree is empty, then it's trivially a prefix
|
||||||
// of the second tree, so no proof is needed.
|
// of the second tree, so no proof is needed.
|
||||||
if len(proof) != 0 {
|
if len(proof) != 0 {
|
||||||
return false, nil
|
return false
|
||||||
}
|
}
|
||||||
return true, &MerkleTreeBuilder{stack: []ct.MerkleTreeNode{}, numLeaves: 0}
|
return true
|
||||||
}
|
}
|
||||||
// Guaranteed that 0 < first.TreeSize < second.TreeSize
|
// Guaranteed that 0 < first.TreeSize < second.TreeSize
|
||||||
|
|
||||||
|
@ -58,12 +57,11 @@ func VerifyConsistencyProof(proof ct.ConsistencyProof, first *ct.SignedTreeHead,
|
||||||
lastNode /= 2
|
lastNode /= 2
|
||||||
}
|
}
|
||||||
|
|
||||||
var leftHashes []ct.MerkleTreeNode
|
|
||||||
var newHash ct.MerkleTreeNode
|
var newHash ct.MerkleTreeNode
|
||||||
var oldHash ct.MerkleTreeNode
|
var oldHash ct.MerkleTreeNode
|
||||||
if node > 0 {
|
if node > 0 {
|
||||||
if len(proof) == 0 {
|
if len(proof) == 0 {
|
||||||
return false, nil
|
return false
|
||||||
}
|
}
|
||||||
newHash = proof[0]
|
newHash = proof[0]
|
||||||
proof = proof[1:]
|
proof = proof[1:]
|
||||||
|
@ -72,22 +70,20 @@ func VerifyConsistencyProof(proof ct.ConsistencyProof, first *ct.SignedTreeHead,
|
||||||
newHash = first.SHA256RootHash[:]
|
newHash = first.SHA256RootHash[:]
|
||||||
}
|
}
|
||||||
oldHash = newHash
|
oldHash = newHash
|
||||||
leftHashes = append(leftHashes, newHash)
|
|
||||||
|
|
||||||
for node > 0 {
|
for node > 0 {
|
||||||
if node%2 == 1 {
|
if node%2 == 1 {
|
||||||
// node is a right child; left sibling exists in both trees
|
// node is a right child; left sibling exists in both trees
|
||||||
if len(proof) == 0 {
|
if len(proof) == 0 {
|
||||||
return false, nil
|
return false
|
||||||
}
|
}
|
||||||
newHash = hashChildren(proof[0], newHash)
|
newHash = hashChildren(proof[0], newHash)
|
||||||
oldHash = hashChildren(proof[0], oldHash)
|
oldHash = hashChildren(proof[0], oldHash)
|
||||||
leftHashes = append(leftHashes, proof[0])
|
|
||||||
proof = proof[1:]
|
proof = proof[1:]
|
||||||
} else if node < lastNode {
|
} else if node < lastNode {
|
||||||
// node is a left child; rigth sibling only exists in the new tree
|
// node is a left child; rigth sibling only exists in the new tree
|
||||||
if len(proof) == 0 {
|
if len(proof) == 0 {
|
||||||
return false, nil
|
return false
|
||||||
}
|
}
|
||||||
newHash = hashChildren(newHash, proof[0])
|
newHash = hashChildren(newHash, proof[0])
|
||||||
proof = proof[1:]
|
proof = proof[1:]
|
||||||
|
@ -97,13 +93,13 @@ func VerifyConsistencyProof(proof ct.ConsistencyProof, first *ct.SignedTreeHead,
|
||||||
}
|
}
|
||||||
|
|
||||||
if !bytes.Equal(oldHash, first.SHA256RootHash[:]) {
|
if !bytes.Equal(oldHash, first.SHA256RootHash[:]) {
|
||||||
return false, nil
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// If trees have different height, continue up the path to reach the new root
|
// If trees have different height, continue up the path to reach the new root
|
||||||
for lastNode > 0 {
|
for lastNode > 0 {
|
||||||
if len(proof) == 0 {
|
if len(proof) == 0 {
|
||||||
return false, nil
|
return false
|
||||||
}
|
}
|
||||||
newHash = hashChildren(newHash, proof[0])
|
newHash = hashChildren(newHash, proof[0])
|
||||||
proof = proof[1:]
|
proof = proof[1:]
|
||||||
|
@ -111,12 +107,10 @@ func VerifyConsistencyProof(proof ct.ConsistencyProof, first *ct.SignedTreeHead,
|
||||||
}
|
}
|
||||||
|
|
||||||
if !bytes.Equal(newHash, second.SHA256RootHash[:]) {
|
if !bytes.Equal(newHash, second.SHA256RootHash[:]) {
|
||||||
return false, nil
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
reverseHashes(leftHashes)
|
return true
|
||||||
|
|
||||||
return true, &MerkleTreeBuilder{stack: leftHashes, numLeaves: first.TreeSize}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func hashNothing() ct.MerkleTreeNode {
|
func hashNothing() ct.MerkleTreeNode {
|
||||||
|
|
|
@ -176,7 +176,7 @@ func (ctlog *logHandle) audit () error {
|
||||||
|
|
||||||
for _, sth := range sths {
|
for _, sth := range sths {
|
||||||
if sth.TreeSize > ctlog.verifiedSTH.TreeSize {
|
if sth.TreeSize > ctlog.verifiedSTH.TreeSize {
|
||||||
isValid, _, _, err := ctlog.scanner.CheckConsistency(ctlog.verifiedSTH, sth)
|
isValid, err := ctlog.scanner.CheckConsistency(ctlog.verifiedSTH, sth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error fetching consistency proof between %d and %d (if this error persists, it should be construed as misbehavior by the log): %s", ctlog.verifiedSTH.TreeSize, sth.TreeSize, err)
|
return fmt.Errorf("Error fetching consistency proof between %d and %d (if this error persists, it should be construed as misbehavior by the log): %s", ctlog.verifiedSTH.TreeSize, sth.TreeSize, err)
|
||||||
}
|
}
|
||||||
|
@ -188,7 +188,7 @@ func (ctlog *logHandle) audit () error {
|
||||||
return fmt.Errorf("Error storing verified STH: %s", err)
|
return fmt.Errorf("Error storing verified STH: %s", err)
|
||||||
}
|
}
|
||||||
} else if sth.TreeSize < ctlog.verifiedSTH.TreeSize {
|
} else if sth.TreeSize < ctlog.verifiedSTH.TreeSize {
|
||||||
isValid, _, _, err := ctlog.scanner.CheckConsistency(sth, ctlog.verifiedSTH)
|
isValid, err := ctlog.scanner.CheckConsistency(sth, ctlog.verifiedSTH)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error fetching consistency proof between %d and %d (if this error persists, it should be construed as misbehavior by the log): %s", ctlog.verifiedSTH.TreeSize, sth.TreeSize, err)
|
return fmt.Errorf("Error fetching consistency proof between %d and %d (if this error persists, it should be construed as misbehavior by the log): %s", ctlog.verifiedSTH.TreeSize, sth.TreeSize, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,12 +211,12 @@ func (s *Scanner) GetSTH() (*ct.SignedTreeHead, error) {
|
||||||
return latestSth, nil
|
return latestSth, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Scanner) CheckConsistency(first *ct.SignedTreeHead, second *ct.SignedTreeHead) (bool, *MerkleTreeBuilder, ct.ConsistencyProof, error) {
|
func (s *Scanner) CheckConsistency(first *ct.SignedTreeHead, second *ct.SignedTreeHead) (bool, error) {
|
||||||
var proof ct.ConsistencyProof
|
var proof ct.ConsistencyProof
|
||||||
|
|
||||||
if first.TreeSize > second.TreeSize {
|
if first.TreeSize > second.TreeSize {
|
||||||
// No way this can be valid
|
// No way this can be valid
|
||||||
return false, nil, nil, nil
|
return false, nil
|
||||||
} else if first.TreeSize == second.TreeSize {
|
} else if first.TreeSize == second.TreeSize {
|
||||||
// The proof *should* be empty, so don't bother contacting the server.
|
// The proof *should* be empty, so don't bother contacting the server.
|
||||||
// This is necessary because the digicert server returns a 400 error if first==second.
|
// This is necessary because the digicert server returns a 400 error if first==second.
|
||||||
|
@ -225,12 +225,11 @@ func (s *Scanner) CheckConsistency(first *ct.SignedTreeHead, second *ct.SignedTr
|
||||||
var err error
|
var err error
|
||||||
proof, err = s.logClient.GetConsistencyProof(int64(first.TreeSize), int64(second.TreeSize))
|
proof, err = s.logClient.GetConsistencyProof(int64(first.TreeSize), int64(second.TreeSize))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, nil, err
|
return false, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
valid, treeBuilder := VerifyConsistencyProof(proof, first, second)
|
return VerifyConsistencyProof(proof, first, second), nil
|
||||||
return valid, treeBuilder, proof, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Scanner) MakeMerkleTreeBuilder(sth *ct.SignedTreeHead) (*MerkleTreeBuilder, error) {
|
func (s *Scanner) MakeMerkleTreeBuilder(sth *ct.SignedTreeHead) (*MerkleTreeBuilder, error) {
|
||||||
|
|
Loading…
Reference in New Issue