72 lines
1.5 KiB
Go
72 lines
1.5 KiB
Go
package digest
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// ForbiddenKeys are argument names rejected by digests-only tools.
|
|
var ForbiddenKeys = []string{
|
|
"content",
|
|
"bytes",
|
|
"file",
|
|
"data",
|
|
"path",
|
|
"body",
|
|
"payload",
|
|
"blob",
|
|
"archive",
|
|
}
|
|
|
|
var (
|
|
hex64 = regexp.MustCompile(`^[0-9a-f]{64}$`)
|
|
forbiddenLower = func() map[string]struct{} {
|
|
m := make(map[string]struct{}, len(ForbiddenKeys))
|
|
for _, k := range ForbiddenKeys {
|
|
m[strings.ToLower(k)] = struct{}{}
|
|
}
|
|
return m
|
|
}()
|
|
)
|
|
|
|
// NormalizeSHA256 strips an optional "sha256:" prefix, lowercases, and
|
|
// requires exactly 64 hexadecimal characters.
|
|
func NormalizeSHA256(s string) (string, error) {
|
|
raw := strings.TrimSpace(s)
|
|
if strings.HasPrefix(strings.ToLower(raw), "sha256:") {
|
|
raw = strings.TrimSpace(raw[len("sha256:"):])
|
|
}
|
|
raw = strings.ToLower(raw)
|
|
if !hex64.MatchString(raw) {
|
|
return "", fmt.Errorf("sha256 must be 64 hexadecimal characters")
|
|
}
|
|
return raw, nil
|
|
}
|
|
|
|
// AssertDigestOnly rejects maps that include any ForbiddenKeys (case-insensitive).
|
|
func AssertDigestOnly(args map[string]any) error {
|
|
if args == nil {
|
|
return nil
|
|
}
|
|
var bad []string
|
|
seen := make(map[string]struct{})
|
|
for k := range args {
|
|
lk := strings.ToLower(k)
|
|
if _, ok := forbiddenLower[lk]; ok {
|
|
if _, dup := seen[lk]; !dup {
|
|
seen[lk] = struct{}{}
|
|
bad = append(bad, k)
|
|
}
|
|
}
|
|
}
|
|
if len(bad) == 0 {
|
|
return nil
|
|
}
|
|
sort.Strings(bad)
|
|
return fmt.Errorf(
|
|
"client refuses to send content/bytes to stamp/verify/hash_report; got: %s",
|
|
strings.Join(bad, ", "),
|
|
)
|
|
}
|