Files
ietf-wimse-ect/refimpl/IMPROVEMENTS.md
Christian Nennemann ba38569319 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.
2026-04-11 17:51:29 +02:00

4.0 KiB
Raw Permalink Blame History

Possible Improvements (Go & Python Refimpls)

Suggestions that could make the implementations more robust, spec-strict, or production-friendly. All items below have been implemented in both refimpls unless noted.


1. Spec alignment

  • ext size/depth (Section 4.2.7)
    Done. Both refimpls reject when serialized ect_ext exceeds 4096 bytes or JSON depth exceeds 5 (ValidateExt / validate_ext). Used in create and verify.

  • jti / wid format
    Done. Optional UUID (RFC 9562) validation: CreateOptions.ValidateUUIDs / VerifyOptions.ValidateUUIDs (Go), validate_uuids (Python). Helpers: ValidUUID / valid_uuid.


2. API and safety

  • Payload mutation in Create
    Done. Documented in both: Create may set Iat, Exp, Sub, Par when zero/nil. Go: comment on Create(); Python: create works on a deep copy so the callers payload is not modified.

  • Structured errors (Go)
    Done. Sentinel errors in ect/errors.go: ErrExpired, ErrReplay, ErrInvalidSignature (wrapped), ErrInvalidTyp, ErrPolPolDecisionPair, etc. Verify and create return these where applicable.


3. Production / operations

  • Replay cache
    Done. Documented: JTICache is in-memory; for multi-instance deployments a shared store (Redis, DB) is required. See refimpl README and go-lang/README “Replay cache (multi-instance)”.

  • Observability
    Done. Go: VerifyOptions.LogVerify func(jti string, err error) called after each verify. Python: VerifyOptions.on_verify_attempt(jti, err) callback.


4. Small cleanups

  • Python Ledger docstring
    Done. “Lookup by task id (jti)”.

  • Python verify
    Done. Documented that par may be set to [] when missing; from_claims already supplies [], so mutation is defensive only.

  • par length
    Done. Go: CreateOptions.MaxParLength, VerifyOptions.MaxParLength, DAGConfig.MaxParLength (0 = no limit; default 100 in DAG). Python: CreateOptions.max_par_length, VerifyOptions.max_par_length, DAGConfig.max_par_length.


5. Nice-to-have

  • inp_hash / out_hash format
    Done. Optional check in create and verify: plain base64url without algorithm prefix, per -01 spec and RFC 9449. Helpers: ValidateHashFormat / validate_hash_format.

  • Constant-time comparison
    Done. Go: crypto/subtle.ConstantTimeCompare for typ in verify. Python: hmac.compare_digest for typ.


Summary: All listed improvements are implemented. For production, also consider: key rotation, WIT integration, and metrics around verify/create latency and error kinds.


6. draft-01 migration (PARTIALLY IMPLEMENTED)

The refimpl was built against draft-nennemann-wimse-ect-00. The -01 draft introduced breaking changes:

  • Rename par to pred: Done. Struct fields, JSON tags, serialization/deserialization, tests, testdata, READMEs updated in both Go and Python.
  • Remove pol and pol_decision: Done. Policy claims removed from core Payload. DAG policy checks now read from ect_ext. Tests and demos updated to use ext.
  • Remove sub: Done. Removed from Payload struct (Go) and dataclass (Python). Create no longer defaults sub=iss.
  • Update typ default: Done. exec+jwt is now preferred; wimse-exec+jwt accepted for backward compat. Verify checks both (constant-time).
  • Update MaxParLength naming: Done. Renamed to MaxPredLength / max_pred_length everywhere.
  • Add L1 support: The -01 draft introduces unsigned JSON ECTs (Level 1). The refimpl currently only supports L2 (signed JWS).
  • Add L3 support: The -01 draft introduces audit ledger requirements for Level 3. The existing in-memory ledger needs hash chain and receipt support.
  • Update hash format: Done. Both Go and Python validate plain base64url without algorithm prefix, consistent with -01 spec and RFC 9449.