Independent Verification of an Asqav Receipt
You can check an Asqav receipt on your own machine without an Asqav account. The format and verifier are published. Retain the signed bytes and public-key material whose provenance you have established, then check the signature locally. This checks the signed record under that key; it does not establish the truth or completeness of the submitted event.
Local verification lets a reviewer examine a signed record without relying on the issuer's hosted answer. It supports integrity review, but the signature alone does not establish event truth, evidentiary weight or compliance with recordkeeping obligations.
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 public keys at
GET /.well-known/jwks.json. Establish the provenance of the key material you use and retain it with the record; a key id selects a key but does not establish trust in it. - 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 the receipt, trusted key material and verifier retained, signature checking runs locally without querying Asqav. You still rely on the signing key's custody, the provenance of the public key and the verifier. A holder of the private key can sign another record; publication alone does not prevent that. Offline verification checks the bytes you retained against the key you selected.
The exact offline checks
The standalone verifier checks signed payloads, predecessor links and supported anchor proofs. Its cryptographic checks use the dependencies and trust material described below.
- Signature. It verifies supported ML-DSA-65 (NIST FIPS 204), Ed25519 or ES256 signatures over the canonical signed payload against the selected public key. Trust in that key and its custody must be established separately.
- 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 id against the supplied public-key directory. The directory's provenance determines whether that key is trustworthy.
- 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 committed envelope digest and checks supported RFC 3161 signatures against caller-pinned TSA keys. It checks OpenTimestamps block placement against caller-supplied Bitcoin header information. Anchor presence alone cannot pass the check.
- 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.
ML-DSA-65 receipt verification uses dilithium-py. Supported classical signatures and TSA certificates use cryptography. Missing dependencies or required trust material can leave a check unverifiable; a skipped cryptographic check does not establish authenticity.
How an auditor verifies a receipt offline
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 dependencies for receipt signatures and TSA certificates:
python -m pip install dilithium-py cryptography - Save the receipt and the public key directory:
curl -fsS -H 'Accept: application/json' 'https://api.asqav.com/api/v1/verify/<receipt-id>' > receipt.json curl -fsS '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
For RFC 3161 anchors, add --tsa-key FILE with a TSA public key or certificate you have chosen to trust. For OpenTimestamps, add --bitcoin-headers FILE with trusted Bitcoin block information. Supplying those files supports the corresponding proof checks; it does not make the standalone verifier validate a certificate chain to a public root or independently authenticate the Bitcoin header source.
The tool prints a per-axis report and an overall verdict. Exit code 0 means verified or verified_keyed; exit code 1 means unverified with failure_class: invalid; exit code 2 means unverified with failure_class: unverifiable. Expiry is reported separately from the verdict, and an omitted predecessor alone does not block verification. To check the negative case, alter a field in the signed payload and confirm that signature verification fails under the same public key.
The public shape fixture can be inspected without an account:
python verify_receipt.py --id sig_example_regulator_cold_verify_2026
This fixture contains placeholder signature and anchor values, and its issuer key is not in the public directory. It illustrates the response format; it is not a cryptographically verified receipt. The standalone verifier reports unverified with failure_class: unverifiable and exit code 2, with its signature and anchor checks skipped. To check a real receipt, supply its signed bytes, matching trusted public-key material and any trust inputs required by its anchors; a real receipt ID alone does not guarantee a verified result.
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
Read the per-axis results: signature verification, a predecessor check and anchor proof verification establish different properties. A passing signature does not verify the truth of the event or substitute for checking its anchors.
Offline verification with the open verifier proves:
- the signature verifies under the selected public key, assuming the cryptographic scheme holds;
- the signed payload matches the bytes authenticated by that signature; unsigned envelope fields need separate checks;
- 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 RFC 3161 certificate chain to a public root. The standalone verifier checks supported timestamp signatures against keys you pin; certificate-chain validation requires a verifier that implements that check and the relevant trust material.
- the absolute position of the receipt in the full chain. Re-walking a chain needs every intervening receipt and evidence of its boundaries; a time-window export may omit predecessors or successors.
- resolution of the
policy_digestto the policy artefact it names. That artefact lives in the export, not in a single receipt.
An audit pack can supply the surrounding records and available anchor material. Preserve the signed bytes and trusted key material when exporting. Checking a timestamp certificate chain requires the relevant certificates, trust roots and a verifier that implements that check; supplying an export does not add that check to the standalone verifier.
The signed bytes and a trusted public key support local signature verification. An audit pack supplies additional material for checks of the record set and available anchors, subject to the verifier's supported checks and the trust assumptions for each proof. Retain that material, the verifier and its dependencies for future audits; do not depend on the live key directory remaining available.
How this supports records review
SEC Rule 17a-4(f)(3)(v)(A) permits the required undertakings to be signed by either a designated executive officer or a designated third party. The unaffiliated-party definition in paragraph (f)(1)(vi) applies to the third-party option. Receipt verification supports integrity checks; it does not itself satisfy the undertaking or the recordkeeping requirements.
A reviewer can check a receipt without querying Asqav or the customer whose agent submitted it. With fixed signed bytes, a fixed public key and a compatible verifier, the signature result is reproducible. The reviewer must still establish the key's provenance and custody, and seek corroboration for event truth, timing and completeness.
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.