fix: update hash format validation to -01 spec (plain base64url, no prefix)
Go ValidateHashFormat was still validating the old -00 format (algorithm:base64url with sha-256/sha-384/sha-512 prefix). Updated to validate plain base64url without prefix per -01 spec and RFC 9449. Python was already updated but uncommitted. Both refimpls now match.
This commit is contained in:
@@ -14,9 +14,6 @@ DEFAULT_MAX_PRED_LENGTH = 100
|
||||
_UUID_RE = re.compile(
|
||||
r"^[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}$"
|
||||
)
|
||||
_ALLOWED_HASH_ALGS = frozenset(("sha-256", "sha-384", "sha-512"))
|
||||
|
||||
|
||||
def _json_depth(obj: Any, depth: int = 0) -> int:
|
||||
if depth > EXT_MAX_DEPTH:
|
||||
return depth
|
||||
@@ -44,22 +41,22 @@ def valid_uuid(s: str) -> bool:
|
||||
|
||||
|
||||
def validate_hash_format(s: str) -> None:
|
||||
"""Raise ValueError if s is non-empty and not algorithm:base64url (sha-256, sha-384, sha-512)."""
|
||||
"""Raise ValueError if s is non-empty and not plain base64url per RFC 9449 / ECT spec.
|
||||
|
||||
The ECT spec (draft-nennemann-wimse-ect-01) and RFC 9449 specify
|
||||
``base64url(SHA-256(data))`` — a plain base64url string without any
|
||||
algorithm prefix. This matches how ACT handles hashes.
|
||||
"""
|
||||
if not s:
|
||||
return
|
||||
idx = s.find(":")
|
||||
if idx <= 0:
|
||||
raise ValueError("ect: inp_hash/out_hash must be algorithm:base64url (e.g. sha-256:...)")
|
||||
alg = s[:idx].lower()
|
||||
if alg not in _ALLOWED_HASH_ALGS:
|
||||
raise ValueError("ect: inp_hash/out_hash must be algorithm:base64url (e.g. sha-256:...)")
|
||||
encoded = s[idx + 1:]
|
||||
if not encoded:
|
||||
raise ValueError("ect: inp_hash/out_hash must be algorithm:base64url (e.g. sha-256:...)")
|
||||
pad = 4 - len(encoded) % 4
|
||||
if pad != 4:
|
||||
encoded += "=" * pad
|
||||
# Reject strings containing non-base64url characters.
|
||||
# base64url alphabet: A-Z a-z 0-9 - _ (no padding '=' expected)
|
||||
if not re.fullmatch(r"[A-Za-z0-9_-]+", s):
|
||||
raise ValueError("ect: inp_hash/out_hash must be plain base64url (no prefix)")
|
||||
# Verify it actually decodes.
|
||||
pad = 4 - len(s) % 4
|
||||
padded = s + "=" * pad if pad != 4 else s
|
||||
try:
|
||||
base64.urlsafe_b64decode(encoded)
|
||||
base64.urlsafe_b64decode(padded)
|
||||
except Exception:
|
||||
raise ValueError("ect: inp_hash/out_hash must be algorithm:base64url (e.g. sha-256:...)") from None
|
||||
raise ValueError("ect: inp_hash/out_hash must be plain base64url (no prefix)") from None
|
||||
|
||||
Reference in New Issue
Block a user