| // 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 |
| } |