#!/usr/bin/env python3 """ Wire-representation checks for draft-hawkins-scitt-attested-agent-payment-01. Text under test: sha256 9e6deb7c735a5f776809e3e1431c7e67e1ecc664ab2c0a94895d51778f4080a7 Four values the text makes load-bearing are examined for whether two independent implementations, given the same bytes, produce the same value. Each check states what the text says, what it does not say, and what two conformant implementations can therefore do differently. Where there is nothing to execute, the check says so instead of pretending. W1 scope digest: the text mandates deterministic CBOR (RFC 8949 s4.2.1) and says the digest is computed over exactly those bytes, and that the digest is how a scope is referenced in Receipts, reports and holds. It names no hash function for this digest; the only SHA-256 statements in the document fix the APK thumbprint. W2 sub: the text says the sub of the scope's Signed Statement is the scope digest of the initial scope. It does not say how digest bytes become the claim value. W3 execution digest: the text lists the fields (amount, payee, settlement timestamp, scope digest) and promises recomputability by any party holding the payment's terms. It names no hash function, no serialization, no timestamp precision; and the payment intent identifier, introduced by Check 5 as the payment's identity, is not among the fields. W4 sequence number: the text requires an explicit monotonic sequence number carried in each Signed Statement. It defines no member name, no label, no type, and no encoding, nor is the result defined if two statements in one sequence carry the same number. There is nothing to execute; recorded as not executable. """ import hashlib, base64, cbor2 SCOPE = {"apk": b"\x00" * 32, "code": {"alg": "sha-256", "artifact": "tdx-mrtd", "digest": b"\x11" * 32}, "limits": {"currency": "USDC", "scale": 6, "per_payment": 10_000, "aggregate": 50_000, "window": 86_400}, "expiry": 1_786_000_000, "executor": "exec.example"} BYTES = cbor2.dumps(SCOPE, canonical=True) # the exact bytes the text prescribes print("W1 scope digest: hash function unspecified") d256 = hashlib.sha256(BYTES).hexdigest() d384 = hashlib.sha384(BYTES).hexdigest() print(f" implementation A (SHA-256): {d256[:32]}...") print(f" implementation B (SHA-384): {d384[:32]}...") print(" same prescribed bytes, both conformant, different scope identifiers;") print(" every digest-keyed reference (Receipt, report, hold, Check 5 selection)") print(" diverges. FINDING: the digest algorithm must be fixed by the profile.\n") print("W2 sub: byte-to-claim representation unspecified") raw = hashlib.sha256(BYTES).digest() sub_hex = raw.hex() sub_b64 = base64.urlsafe_b64encode(raw).rstrip(b"=").decode() print(f" implementation A (lowercase hex): {sub_hex[:32]}...") print(f" implementation B (base64url): {sub_b64[:32]}...") print(" both honestly put 'the scope digest' in sub; their (iss, sub) queries") print(" never meet, so each sees the other's sequence as nonexistent.") print(" FINDING: the representation must be fixed by the profile.\n") print("W3 execution digest: underspecified, and intent identity absent") def exec_digest(amount, payee, ts, scope_digest): return hashlib.sha256( cbor2.dumps([amount, payee, ts, scope_digest], canonical=True)).hexdigest() p1 = exec_digest(10_000, "merchant.example", 1_786_000_000, raw) # intent-A p2 = exec_digest(10_000, "merchant.example", 1_786_000_000, raw) # intent-B print(f" payment 1 (intent-A): {p1[:32]}...") print(f" payment 2 (intent-B): {p2[:32]}...") print(f" identical: {p1 == p2}") print(" two DISTINCT payments (different intent identifiers) have identical") print(" digest inputs over the fields the text names. The hash function,") print(" field serialization and timestamp precision are unstated, so the") print(" promised third-party recomputation is not defined. Whether an") print(" enumeration preserves repeated identical digests is not specified;") print(" the counting consequence is recorded as an ambiguity, not as a") print(" demonstrated undercount. FINDING: fix the field set (include the") print(" intent identifier), the hash function, and the serialization.\n") print("W4 sequence number: no wire definition") print(" Required to exist and be monotonic; no claim or member label, type,") print(" or encoding is given, nor is the result defined if two statements") print(" in one sequence carry the same sequence number. Nothing to execute.") print(" FINDING recorded from the text alone.")