fleet/orbit/pkg/update/hash.go
Tomas Touceda 3ac8494d23 Add 'orbit/' from commit 'ab3047bb39f1e2be331d1ff18b4eb768619033c4'
git-subtree-dir: orbit
git-subtree-mainline: d5974aad97
git-subtree-split: ab3047bb39
2021-08-04 16:58:25 -03:00

59 lines
1.4 KiB
Go

package update
import (
"bytes"
"crypto/sha256"
"crypto/sha512"
"hash"
"io"
"os"
"github.com/pkg/errors"
"github.com/theupdateframework/go-tuf/data"
)
// CheckFileHash checks the file at the local path against the provided hash
// functions.
func CheckFileHash(meta *data.TargetFileMeta, localPath string) error {
hashFunc, hashVal, err := selectHashFunction(meta)
if err != nil {
return err
}
f, err := os.Open(localPath)
if err != nil {
return errors.Wrap(err, "open file for hash")
}
defer f.Close()
if _, err := io.Copy(hashFunc, f); err != nil {
return errors.Wrap(err, "read file for hash")
}
if !bytes.Equal(hashVal, hashFunc.Sum(nil)) {
return errors.Errorf("hash %s does not match expected: %s", data.HexBytes(hashFunc.Sum(nil)), data.HexBytes(hashVal))
}
return nil
}
// selectHashFunction returns the first matching hash function and expected
// hash, otherwise returning an error if not matching hash can be found.
//
// SHA512 is preferred, and SHA256 is returned if 512 is not available.
func selectHashFunction(meta *data.TargetFileMeta) (hash.Hash, []byte, error) {
for hashName, hashVal := range meta.Hashes {
if hashName == "sha512" {
return sha512.New(), hashVal, nil
}
}
for hashName, hashVal := range meta.Hashes {
if hashName == "sha256" {
return sha256.New(), hashVal, nil
}
}
return nil, nil, errors.Errorf("no matching hash function found: %v", meta.HashAlgorithms())
}