blob: 1a8105d610f79e7dc7ca3340b52b7256e696fb59 [file] [log] [blame] [edit]
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package releaseauth
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
"log"
)
// SHA256Hash represents a 256-bit SHA hash
type SHA256Hash [sha256.Size]byte
// ErrInvalidSHA256Hash is returned when the hash is invalid
var ErrInvalidSHA256Hash = errors.New("the value was not a valid SHA-256 hash")
// SHA256FromHex decodes a SHA256Hash from a hex string dump
func SHA256FromHex(hashHex string) (SHA256Hash, error) {
var result [sha256.Size]byte
hash, err := hex.DecodeString(hashHex)
if err != nil || len(hash) != sha256.Size {
return result, ErrInvalidSHA256Hash
}
if copy(result[:], hash) != sha256.Size {
panic("could not copy hash value")
}
return result, nil
}
// SHA256Checksums decodes a file generated by the sha256sum program
type SHA256Checksums map[string]SHA256Hash
func ParseChecksums(data []byte) (SHA256Checksums, error) {
items := bytes.Split(data, []byte("\n"))
result := make(map[string]SHA256Hash, len(items))
for _, line := range items {
parts := bytes.SplitN(line, []byte(" "), 2)
if len(parts) != 2 {
break
}
log.Printf("[TRACE] parsing SHA256SUMS %q = %q", parts[0], parts[1])
hash, err := SHA256FromHex(string(parts[0]))
if err != nil {
return result, fmt.Errorf("failed to parse checksums: %w", err)
}
result[string(parts[1])] = hash
}
return result, nil
}
// Validate retrieves a SHA256Hash for the a filename and compares it
// to the specified hash. Validate returns an error if the hash is not found
// or if it does not match.
func (c SHA256Checksums) Validate(filename string, hash SHA256Hash) error {
sum, ok := c[filename]
if !ok {
return fmt.Errorf("no checksum found for filename %q", filename)
}
if sum != hash {
return fmt.Errorf("checksums do not match")
}
return nil
}