mirror of https://github.com/docker/docs.git
Utility function for comparing multihash
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
This commit is contained in:
parent
0256cee017
commit
ade6b0736e
|
@ -161,6 +161,44 @@ func CheckHashes(payload []byte, name string, hashes Hashes) error {
|
||||||
return nil
|
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
|
// CheckValidHashStructures returns an error, or nil, depending on whether
|
||||||
// the content of the hashes is valid or not.
|
// the content of the hashes is valid or not.
|
||||||
func CheckValidHashStructures(hashes Hashes) error {
|
func CheckValidHashStructures(hashes Hashes) error {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package data
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/go/canonical/json"
|
"github.com/docker/go/canonical/json"
|
||||||
|
@ -176,3 +177,52 @@ func TestCheckValidHashStructures(t *testing.T) {
|
||||||
err = CheckValidHashStructures(hashes)
|
err = CheckValidHashStructures(hashes)
|
||||||
require.IsType(t, ErrInvalidChecksum{}, err)
|
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)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue