blob: a13968c6fa398160ab844bfb7d8c6978f6f74b26 [file] [log] [blame]
package util
import (
"crypto/hmac"
"crypto/sha512"
"encoding/hex"
"errors"
"fmt"
"io"
"github.com/flynn/go-tuf/data"
)
var ErrWrongLength = errors.New("wrong length")
type ErrWrongHash struct {
Type string
Expected data.HexBytes
Actual data.HexBytes
}
func (e ErrWrongHash) Error() string {
return fmt.Sprintf("wrong %s hash, expected %s got %s", e.Type, hex.EncodeToString(e.Expected), hex.EncodeToString(e.Actual))
}
type ErrNoCommonHash struct {
Expected map[string]data.HexBytes
Actual map[string]data.HexBytes
}
func (e ErrNoCommonHash) Error() string {
types := func(a map[string]data.HexBytes) []string {
t := make([]string, 0, len(a))
for typ := range a {
t = append(t, typ)
}
return t
}
return fmt.Sprintf("no common hash function, expected one of %s, got %s", types(e.Expected), types(e.Actual))
}
func FileMetaEqual(actual data.FileMeta, expected data.FileMeta) error {
if actual.Length != expected.Length {
return ErrWrongLength
}
hashChecked := false
for typ, hash := range expected.Hashes {
if h, ok := actual.Hashes[typ]; ok {
hashChecked = true
if !hmac.Equal(h, hash) {
return ErrWrongHash{typ, hash, h}
}
}
}
if !hashChecked {
return ErrNoCommonHash{expected.Hashes, actual.Hashes}
}
return nil
}
func GenerateFileMeta(r io.Reader) (data.FileMeta, error) {
h := sha512.New()
n, err := io.Copy(h, r)
if err != nil {
return data.FileMeta{}, err
}
return data.FileMeta{
Length: n,
Hashes: map[string]data.HexBytes{"sha512": h.Sum(nil)},
}, nil
}