How to verify a receipt offline with openssl
The promise of receipts.you is that the cryptographic guarantee outlives us. If our service is taken down tomorrow, every receipt issued to date should still verify — provided you have the inputs and a working openssl. This post lays out the exact recipe: five commands, no service dependency, runs on any laptop with standard cryptography tooling.
What you need before our service vanishes
Three artifacts. Download them from your receipt page now and store them durably alongside the original screenshot file.
- The receipt JSON. Available on every receipt page via the “Download receipt” link. Contains the SHA hash, perceptual hashes, timestamp, signature, and OpenTimestamps inclusion proof.
- Our public key. PEM-formatted ECDSA P-256 key published at
/.well-known/receipts-pubkey.pem— download once, store with your evidence. - The original screenshot file. The bytes you sealed. The whole verification chain bottoms out here.
With these three plus openssl and the OpenTimestamps client, the verification is fully offline.
The five commands
1. Hash the file yourself
openssl dgst -sha256 -hex screenshot.png
# outputs: SHA256(screenshot.png)= <64-char hex>Compare to hash in the receipt JSON. Match means the file is byte-identical to what was sealed. If it's a recompressed copy, this will mismatch — that's where perceptual hash verification kicks in (which isn't in this minimal recipe).
2. Reconstruct the signed payload
# The signature is over: hash || ":" || iso8601_timestamp
# Example: f1a2...beef:2026-05-25T14:32:00.000Z
echo -n "<hash>:<iso_timestamp>" > payload.txtThe exact payload format is documented at /methodology. Copy the SHA-256 hex and the ISO timestamp directly out of the receipt JSON, concatenated by a colon, no trailing newline.
3. Verify the ECDSA signature
# signature is base64-encoded in the receipt JSON
echo -n "<base64_signature>" | base64 -d > signature.bin
openssl dgst -sha256 -verify pubkey.pem -signature signature.bin payload.txt
# outputs: Verified OK“Verified OK” means the signature was made by whoever holds the private key paired with pubkey.pem — i.e., us — and covers exactly the hash + timestamp in the receipt. Tampering with either the hash or the timestamp breaks verification.
4. Verify the OpenTimestamps anchor
# Install the OTS reference client if needed
pip install opentimestamps-client
# The OTS proof is in the receipt JSON as base64
echo -n "<base64_ots_proof>" | base64 -d > screenshot.png.ots
# Verify — needs a Bitcoin block-header source (the client uses public ones)
ots verify screenshot.png.ots
# outputs: Success! Bitcoin attests data existed as of <date>The OTS client reads the inclusion proof, follows the Merkle path to the Bitcoin block embedding, and confirms the block attests the hash existed at the block timestamp. This is the external anchor that survives us going away.
5. (Optional) Cross-check with a fresh hash
# Sanity check: rehash the file and confirm it matches what's anchored
openssl dgst -sha256 -hex screenshot.png
# Compare to the hash field in receipt JSONBelt and braces — you already did this in step 1, but re-checking after the OTS verification confirms the whole chain links cleanly.
What this gives you
- Independence from receipts.you the service. The whole verification runs locally; we're not in the loop.
- Independence from openssl version drift. The ECDSA P-256 / SHA-256 primitives are cryptographic standards; any openssl from the last decade works.
- Independence from the OTS calendar servers (after the anchor cures). Once the OTS inclusion proof references a Bitcoin block, you only need a Bitcoin block-header source to verify. Multiple public ones exist; the OTS client uses several by default.
What this doesn't cover
The five-command recipe verifies the SHA layer. It doesn't run perceptual-hash verification (you'd need our pHash/dHash implementation, available on GitHub). For evidence where the file has been recompressed by a messaging platform, you'd run the perceptual-hash check separately. For most evidence workflows where the original file is preserved, the SHA check is sufficient and binary.
When to use this
Three realistic situations:
- The matter is in court and the judge wants independent verification. An expert witness can run the five commands on a court-acceptable laptop and confirm the chain. No reliance on our online service.
- Long-horizon evidence preservation (decades). For evidence that may matter in 10-50 years, download the receipt artifacts now. The cryptographic primitives outlive us and outlive most service providers.
- Security-engineer audit. Verifying our claims without trusting our infrastructure is the kind of thing engineers reasonably want to do before adopting a tool for sensitive workflows. The five commands make this straightforward.
For the methodology specification (signed payload format, key rotation policy, OTS protocol details), see /methodology.