mirror of
https://github.com/anchore/syft.git
synced 2026-10-31 22:46:36 +01:00
add file source digest support (#1914)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/anchore/syft/syft/file"
|
||||
)
|
||||
|
||||
func supportedHashAlgorithms() []crypto.Hash {
|
||||
return []crypto.Hash{
|
||||
crypto.MD5,
|
||||
crypto.SHA1,
|
||||
crypto.SHA224,
|
||||
crypto.SHA256,
|
||||
crypto.SHA384,
|
||||
crypto.SHA512,
|
||||
}
|
||||
}
|
||||
|
||||
func NewDigestsFromFile(closer io.ReadCloser, hashes []crypto.Hash) ([]file.Digest, error) {
|
||||
// create a set of hasher objects tied together with a single writer to feed content into
|
||||
hashers := make([]hash.Hash, len(hashes))
|
||||
writers := make([]io.Writer, len(hashes))
|
||||
for idx, hashObj := range hashes {
|
||||
hashers[idx] = hashObj.New()
|
||||
writers[idx] = hashers[idx]
|
||||
}
|
||||
|
||||
size, err := io.Copy(io.MultiWriter(writers...), closer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if size == 0 {
|
||||
return make([]file.Digest, 0), nil
|
||||
}
|
||||
|
||||
result := make([]file.Digest, len(hashes))
|
||||
// only capture digests when there is content. It is important to do this based on SIZE and not
|
||||
// FILE TYPE. The reasoning is that it is possible for a tar to be crafted with a header-only
|
||||
// file type but a body is still allowed.
|
||||
for idx, hasher := range hashers {
|
||||
result[idx] = file.Digest{
|
||||
Algorithm: CleanDigestAlgorithmName(hashes[idx].String()),
|
||||
Value: fmt.Sprintf("%+x", hasher.Sum(nil)),
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func Hashers(names ...string) ([]crypto.Hash, error) {
|
||||
hashByName := make(map[string]crypto.Hash)
|
||||
for _, h := range supportedHashAlgorithms() {
|
||||
hashByName[CleanDigestAlgorithmName(h.String())] = h
|
||||
}
|
||||
|
||||
var hashers []crypto.Hash
|
||||
for _, hashStr := range names {
|
||||
hashObj, ok := hashByName[CleanDigestAlgorithmName(hashStr)]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unsupported hash algorithm: %s", hashStr)
|
||||
}
|
||||
hashers = append(hashers, hashObj)
|
||||
}
|
||||
return hashers, nil
|
||||
}
|
||||
|
||||
func CleanDigestAlgorithmName(name string) string {
|
||||
lower := strings.ToLower(name)
|
||||
return strings.ReplaceAll(lower, "-", "")
|
||||
}
|
||||
Reference in New Issue
Block a user