Files
ietf-wimse-ect/refimpl/go-lang/ect/validate.go
Christian Nennemann bbf557e54b Restructure refimpl into go-lang and python subdirectories
Move Go reference implementation to refimpl/go-lang/ and add new
Python reference implementation in refimpl/python/. Update build.sh
with renamed draft and simplified tool paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 23:11:55 +01:00

84 lines
1.8 KiB
Go

package ect
import (
"encoding/base64"
"encoding/json"
"regexp"
"strings"
)
// ExtMaxSize is the recommended max serialized size of ext (Section 4.2.7).
const ExtMaxSize = 4096
// ExtMaxDepth is the recommended max JSON nesting depth in ext.
const ExtMaxDepth = 5
// DefaultMaxParLength is the recommended max number of parent references.
const DefaultMaxParLength = 100
// uuidRegex matches RFC 9562 UUID: 8-4-4-4-12 hex.
var uuidRegex = regexp.MustCompile(`^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$`)
// allowedHashAlgs are the spec-recommended hash algorithm prefixes for inp_hash/out_hash.
var allowedHashAlgs = map[string]bool{"sha-256": true, "sha-384": true, "sha-512": true}
// ValidateExt returns an error if ext exceeds ExtMaxSize or ExtMaxDepth.
func ValidateExt(ext map[string]interface{}) error {
if ext == nil || len(ext) == 0 {
return nil
}
b, err := json.Marshal(ext)
if err != nil {
return err
}
if len(b) > ExtMaxSize {
return ErrExtSize
}
if depth(b) > ExtMaxDepth {
return ErrExtDepth
}
return nil
}
func depth(b []byte) int {
var max, level int
for _, c := range b {
switch c {
case '{', '[':
level++
if level > max {
max = level
}
case '}', ']':
level--
}
}
return max
}
// ValidUUID returns true if s is a UUID string (RFC 9562).
func ValidUUID(s string) bool {
return uuidRegex.MatchString(s)
}
// ValidateHashFormat returns nil if s is empty or matches "algorithm:base64url" (sha-256, sha-384, sha-512).
func ValidateHashFormat(s string) error {
if s == "" {
return nil
}
idx := strings.Index(s, ":")
if idx <= 0 {
return ErrHashFormat
}
alg := strings.ToLower(s[:idx])
if !allowedHashAlgs[alg] {
return ErrHashFormat
}
encoded := s[idx+1:]
if encoded == "" {
return ErrHashFormat
}
_, err := base64.RawURLEncoding.DecodeString(encoded)
return err
}