Independent Verification of an Asqav Receipt
An Asqav receipt verifies on your own machine, with no Asqav account, and without trusting Asqav. The receipt format is published, the verify key is public, and the verifier is open source. Anyone who holds a receipt can confirm the signature themselves and reject a forged or altered one.
This matters because record-retention rules ask for evidence that an unaffiliated party can check. SEC 17a-4(f)(3)(v) requires a record an independent party can read and verify. NYDFS 23 NYCRR 500.06 and DORA Articles 28 to 30 do not write that into their rule text, but the same property matters in practice, because an examiner or auditor gives no independent weight to a record only its subject can check. A receipt that only its issuer can validate is self-attestation, and self-attestation does not meet that bar. Independent verification is what turns a signed log into evidence.
What independent verification means
Three properties have to hold together, and Asqav publishes all three:
- The wire format is open. The receipt is canonicalised with JCS (RFC 8785), so a verifier reproduces the exact bytes the signer signed. The format is published as draft-marques-asqav-compliance-receipts on the IETF Datatracker.
- The verify key is public. Asqav publishes the post-quantum public key at
GET /.well-known/jwks.json, so you resolve the signing key yourself rather than taking Asqav's word for which key signed. - The verifier is open source. The standalone
verify_receipt.pyis a single readable file you can copy into an audit environment and read line by line.
With those three published, the verification does not route through Asqav. You fetch the receipt and the key once, then run the math locally. Asqav cannot make a forged receipt pass, and Asqav cannot make a genuine one fail.
The exact offline checks
The open verifier runs these checks on your machine. Everything except the post-quantum signature math uses only the Python standard library.
- Signature. It verifies the ML-DSA-65 (NIST FIPS 204) signature over the receipt's canonical bytes against the public key from the key directory. This is the check that actually carries third-party trust.
- Canonical bytes. It reproduces the JCS canonical byte string (sorted keys, no whitespace, UTF-8, NaN and Infinity rejected) so the message it checks is byte-identical to what the signer signed.
- Issuer key. It resolves the signing key by its key id against the public
jwks.jsondirectory, so you never take Asqav's word for which key signed the receipt. - Hash chain. Given the predecessor receipt, it rederives the SHA-256 link and confirms this receipt chains to the one before it.
- Anchors. It recomputes the envelope digest the external anchors commit to and confirms each anchor value is present and well-formed.
- Structure and skew. It confirms the required fields are present, the receipt type sits inside the published namespace, and the issue time is within bounds.
The signature check needs one dependency, dilithium-py, a pure-Python FIPS 204 implementation whose verify path uses only standard-library SHAKE. Nothing compiles. Skip it and every other check still runs, but the signature axis reports as skipped and the verdict drops to INCOMPLETE. The tool never prints PASS unless the post-quantum signature was actually verified.
How an auditor verifies a receipt without trusting Asqav
A regulator, auditor, or counterparty who receives a receipt runs the following. None of it requires an Asqav account or login.
- Save the open verifier. It lives at
python/src/asqav/verifier/verify_receipt.pyin the publicasqav-sdkrepository. Read it first. It is one file. - Install the single dependency for the signature check:
pip install dilithium-py - Save the receipt and the public key directory:
curl https://api.asqav.com/api/v1/verify/<receipt-id> > receipt.json curl https://api.asqav.com/.well-known/jwks.json > jwks.json - Verify with no further network access. The
--offlineflag forbids the tool from reaching out again:python verify_receipt.py --receipt receipt.json --jwks jwks.json --offline - To check the hash-chain link, also save the predecessor receipt and pass it:
python verify_receipt.py --receipt receipt.json --jwks jwks.json \ --predecessor previous.json --offline
The tool prints a per-axis report and an overall verdict. Exit code 0 is PASS (every non-skipped axis passed and the signature verified), 1 is FAIL (at least one axis failed, for example a tampered payload), and 2 is INCOMPLETE (a blocking axis such as the signature was skipped). A regulator who wants to confirm the negative case can alter a single field in receipt.json and watch the signature axis fail.
A public worked example needs no key at all:
python verify_receipt.py --id sig_example_regulator_cold_verify_2026
That fixture is a public documentation example, and its signing key is a reserved example identity that the public key directory does not list. Issuer-key resolution therefore fails and the signature axis is skipped with no key to check it against, while the structure and anchor axes pass, so the overall verdict is FAIL on issuer-key resolution rather than a green PASS. Point --id at one of your own signed receipts, whose key is in the directory, to run the full cryptographic path through to a PASS.
For a live example against a real signature, the receipt verification demo checks a signed receipt in the browser and shows the same signature, timestamp anchor, and raw proof this tool reports.
What offline verification proves, and what it does not
Independent verification is precise about its scope. The honest boundary is the point of the whole exercise.
Offline verification with the open verifier proves:
- the receipt was signed by the key published in Asqav's public key directory
- the signed bytes are exactly the receipt content you are reading, with no field altered
- the receipt chains to its stated predecessor, when you supply that predecessor
- the receipt type is inside the published namespace and the required fields are present.
Offline verification with the open verifier does not, on its own, prove:
- the full RFC3161 timestamp certificate chain. The verifier confirms each anchor binds the envelope and is well-formed. Walking the timestamp authority's certificate chain to its root needs the certificate material that ships in the audit pack.
- the absolute position of the receipt in the full chain. Re-walking the entire chain end to end, rather than one predecessor link, needs the complete receipt set, which the audit pack carries.
- resolution of the
policy_digestto the policy artefact it names. That artefact lives in the export, not in a single receipt.
For those, export the audit pack with asqav audit-pack export. The tarball ships the receipts, the public verify key, the anchor certificate material, and the format reference, so the same offline procedure scales to the full chain and the full timestamp proof. The hosted /verify endpoint also performs the full certificate-chain walk for a single receipt.
The split is deliberate. A single receipt plus the public key proves authorship and integrity offline, which is the property that disqualifies a forged or altered record. The audit pack adds the surrounding evidence a deep audit walks through. Both verify against the same public key, so neither step asks you to trust Asqav.
Why this is the property regulators ask for
The unaffiliated-party requirement in record-retention rules is structural, not a label. SEC 17a-4(f)(3)(v) requires a designated third party "that is not affiliated" with the regulated entity. NYDFS 500.06 and DORA Articles 28 to 30 do not spell that party out in their rule text, but the same property holds up in practice, because an examiner or auditor reads a record only its producer can check as that entity's own narrative rather than independent evidence. A vendor that signs over its own actions cannot satisfy that test, because the evidence and the actor are the same party.
Independent verification is how Asqav makes the property checkable rather than asserted. Because the format, the key, and the verifier are all published, an inbound auditor confirms the receipt without involving Asqav and without involving the customer whose agent acted. The signature either verifies against the published key or it does not, and no party in the chain can change that answer.
See Asqav as third-party notary for the notary role this verification underpins, SEC 17a-4(f)(3)(v), DORA Articles 28-30, and NYDFS 23 NYCRR 500.06 for the regulation walkthroughs, and post-quantum signed receipts for the ML-DSA-65 algorithm choice and threat model.