Verify a consent receipt
Every consent recorded on ConsentHub is signed the moment it is recorded. Drop the receipt here to see whether it is exactly as it was signed. If anything in it has been changed, even one character, this page says so and shows what.
How a receipt is checked
- 1 · Contents
The receipt's payload is put into its canonical form (RFC 8785), the same bytes that were signed.
- 2 · Hash
SHA-256 of those bytes must equal the payload hash recorded in the receipt and in the ledger.
- 3 · Signature
The detached ES256 signature is verified over those bytes with the signing key's public half.
- 4 · Key
The key is named by its id in the receipt. Its fingerprint is shown so you can compare it elsewhere.
Check a receipt here
The check runs in your browser. The page does not ask a server whether the receipt is valid; it only fetches the public keys.
Check it offline, without this website
The same three computations run from the command line with no network and no access to ConsentHub, so a receipt can be checked years later, by an auditor or a court, whether or not this site still exists.
- Step 1
Save the receipt
On the receipt page, use Download receipt (JSON). The file is the signed record itself, not a copy of the page.
- Step 2
Save the public key
The receipt names its key (
kid). Download that key below, or from /api/public/signing-keys. - Step 3
Run the verifier
consenthub-verifyis open source and prints VERIFIED, or the first field that differs. Exit code 0 means verified. Download it below; it needs only Node.js.
The verifier, ready to run
One small archive with the command and the library it uses. There is nothing to install and it never goes online: unzip it on any Windows, Linux or macOS machine that has Node.js 18 or newer. The source is in the archive, so what it does can be read as well as run.
- Windows
Unzip, open Command Prompt or PowerShell in the folder, then:
.\consenthub-verify.cmd --receipt receipt.json --pubkey consenthub-public.pem
- Linux / macOS
Unzip, open a terminal in the folder, then:
./consenthub-verify --receipt receipt.json --pubkey consenthub-public.pem
consenthub-verify --receipt receipt.json --pubkey consenthub-public.pem # → receipt rcp_… — VERIFIED # payload hash : matches # signature : valid (key demo-2026-10)
The output names the key that signed the receipt. A receipt signed before a key rotation verifies with the retired key it names, not with the current one: keep the keys in one folder as <kid>.pub.pem and pass --keyring instead of --pubkey. Change one character of the receipt and run it again: it must fail.
What exactly is computed
- canonical
- The payload serialised under RFC 8785: keys sorted, no whitespace, numbers and strings in their one canonical form. Any equivalent JSON gives the same bytes; any changed value gives different bytes.
- payloadHash
SHA-256(canonical), hex. This is the value the hash-chained ledger covers, so the receipt and the ledger vouch for the same bytes.- signature
- A detached JWS (RFC 7515, Appendix F,
b64:false): ECDSA P-256 with SHA-256 overprotectedHeader + "." + canonical, with the signature as raw R‖S. The header carries the key id. - fingerprint
SHA-256of the public key's DER (SubjectPublicKeyInfo) encoding, hex. The same key always has the same fingerprint, wherever you obtained it.
Signing keys
The public halves of every key ConsentHub signs with, current and retired. A receipt signed before a key rotation still verifies with the retired key it names.
| Key id | Status | Fingerprint (SHA-256) | Download |
|---|---|---|---|
| demo-2026-10 | current | 47eaf7a1058421440b0504ceed4f06ea5f08ed3a1e96b143eef4dc8140dad755 | PEM |
One honest limit. A key served from this site proves that a receipt matches ConsentHub's key. To confirm the key is really ConsentHub's, compare its fingerprint with a copy published somewhere this site does not control, or one you obtained from ConsentHub earlier.