Utility function for comparing multihash

Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
This commit is contained in:
Riyaz Faizullabhoy 2016-05-13 17:42:40 -07:00
parent 0256cee017
commit ade6b0736e
2 changed files with 88 additions and 0 deletions

View File

@ -161,6 +161,44 @@ func CheckHashes(payload []byte, name string, hashes Hashes) error {
return nil
}
// CompareMultiHashes verifies that the two Hashes passed in can represent the same data.
// This means that both maps must have at least one key defined for which they map, and no conflicts.
// Note that we only check supported hashes, like in CheckHashes
func CompareMultiHashes(hashes1, hashes2 Hashes) error {
// First check if the two hash structures are valid
if err := CheckValidHashStructures(hashes1); err != nil {
return err
}
if err := CheckValidHashStructures(hashes2); err != nil {
return err
}
// Check if they have at least one matching hash, and no conflicts
cnt := 0
for _, hashAlg := range NotaryDefaultHashes {
hash1, ok := hashes1[hashAlg]
if !ok {
continue
}
hash2, ok := hashes2[hashAlg]
if !ok {
continue
}
if subtle.ConstantTimeCompare(hash1[:], hash2[:]) == 0 {
return fmt.Errorf("mismatched %s checksum", hashAlg)
}
// If we reached here, we had a match
cnt++
}
if cnt == 0 {
return fmt.Errorf("at least one supported and matching hash needed")
}
return nil
}
// CheckValidHashStructures returns an error, or nil, depending on whether
// the content of the hashes is valid or not.
func CheckValidHashStructures(hashes Hashes) error {

View File

@ -3,6 +3,7 @@ package data
import (
"bytes"
"encoding/hex"
"strings"
"testing"
"github.com/docker/go/canonical/json"
@ -176,3 +177,52 @@ func TestCheckValidHashStructures(t *testing.T) {
err = CheckValidHashStructures(hashes)
require.IsType(t, ErrInvalidChecksum{}, err)
}
func TestCompareMultiHashes(t *testing.T) {
var err error
hashes1 := make(Hashes)
hashes2 := make(Hashes)
// Expected to fail since there are no checksums at all
err = CompareMultiHashes(hashes1, hashes2)
require.Error(t, err)
// Expected to fail even though the checksum of sha384 is valid,
// because we haven't provided a supported hash algorithm yet (ex: sha256).
hashes1["sha384"], err = hex.DecodeString("64becc3c23843942b1040ffd4743d1368d988ddf046d17d448a6e199c02c3044b425a680112b399d4dbe9b35b7ccc989")
hashes2["sha384"], err = hex.DecodeString("64becc3c23843942b1040ffd4743d1368d988ddf046d17d448a6e199c02c3044b425a680112b399d4dbe9b35b7ccc989")
err = CompareMultiHashes(hashes1, hashes2)
require.Error(t, err)
// Now both have a matching sha256, so this will pass
hashes1["sha256"], err = hex.DecodeString("766af0ef090a4f2307e49160fa242db6fb95f071ad81a198eeb7d770e61cd6d8")
hashes2["sha256"], err = hex.DecodeString("766af0ef090a4f2307e49160fa242db6fb95f071ad81a198eeb7d770e61cd6d8")
err = CompareMultiHashes(hashes1, hashes2)
require.NoError(t, err)
// Because the sha384 algorithm isn't supported, it's treated as an extra key that won't be checked
// So even if it doesn't match, that's fine as long as all supported keys match
hashes2["sha384"], err = hex.DecodeString(strings.Repeat("a", 96))
err = CompareMultiHashes(hashes1, hashes2)
require.NoError(t, err)
// only add a sha512 to hashes1, but comparison will still succeed because there's no mismatch and we have the sha256 match
hashes1["sha512"], err = hex.DecodeString("795d9e95db099464b6730844f28effddb010b0d5abae5d5892a6ee04deacb09c9e622f89e816458b5a1a81761278d7d3a6a7c269d9707eff8858b16c51de0315")
err = CompareMultiHashes(hashes1, hashes2)
require.NoError(t, err)
// remove sha256 from hashes1, comparison will fail now because there are no matches
delete(hashes1, "sha256")
err = CompareMultiHashes(hashes1, hashes2)
require.Error(t, err)
// add sha512 to hashes2, comparison will now pass because both have matching sha512s
hashes2["sha512"], err = hex.DecodeString("795d9e95db099464b6730844f28effddb010b0d5abae5d5892a6ee04deacb09c9e622f89e816458b5a1a81761278d7d3a6a7c269d9707eff8858b16c51de0315")
err = CompareMultiHashes(hashes1, hashes2)
require.NoError(t, err)
// change the sha512 for hashes2, comparison will now fail
hashes2["sha512"], err = hex.DecodeString(strings.Repeat("a", notary.Sha512HexSize))
err = CompareMultiHashes(hashes1, hashes2)
require.Error(t, err)
}