Check a receipt, four ways¶
In short. Lightest first. The first three tell you a receipt is the one the Foundation published. The fourth recomputes the answer itself.
1. In your browser, on the receipt's page¶
Each receipt page on habitat.ooo has a verify panel. It computes the receipt's fingerprint in your tab, from the receipt shown on the page, and compares it with the published one. Press Verify in your browser; tick tamper with a copy to change one character and watch it fail. Nothing is fetched and nothing is sent.
This shows the receipt's text is the published text. It doesn't recompute the receipt.
The receipts page also has two small tools of the same kind. Recompute one in your browser recomputes a published digest in your tab from the record's own numbers: reshuffle the rows and it holds, change one value and it moves. It runs on our page and our copy of the numbers, so it is a demonstration, not an independent check; the kit is that. A paste box computes the SHA-256 of any text you type, with nothing sent.
2. On Record, with the Published check¶
Open Record (behind the Desk password until it is fully vetted), and under "Or open a published receipt" click one of the five names, or add the receipt file. Press Check.
Published reads the Foundation's public anchor files from habitat.ooo and runs, in your tab, the nine checks named under way 3: among them that the file's fingerprint is the one signed, the Foundation's signature, that the public log holds this exact entry, the log's proof that the entry is in its tree, and the log's own signatures. When all nine hold, it says so: "yes: exactly as published, signed by Habitat Foundation, logged on …".
This also shows the receipt is the published one, and when it was logged. It doesn't recompute the receipt either.
3. The anchor, offline¶
For a check that needs nothing from us at all, download four files from habitat.ooo into one folder: the verifier
(/receipts/anchors/verify_anchor.py), the two public keys beside it (foundation-receipts-ed25519.pub and
rekor-sigstore-public.pem), and the anchor for the file you want to check. The
anchor index lists every anchor and the file it covers. Then:
python3 verify_anchor.py receipt-keepout-agent-trace.2026-10-16.anchor.json receipt-keepout-agent-trace.json
It needs Python 3 and the cryptography package, makes no network calls, and runs the same nine checks. It prints
PASS or FAIL for each, the time the log recorded, and ALL PASS at the end.
The nine checks, by name
subject_is_record_digest, file_matches_subject, foundation_signature, log_has_payload,
log_has_signature, inclusion_proof, checkpoint_root, checkpoint_signed_by_log,
entry_timestamp_signed_by_log.
A pass shows the file existed, unchanged, at the log's time. It says nothing about whether the receipt's claim is right.
4. The full recompute, with the kit¶
To recompute the answer itself, run the receipt's kit. It rebuilds the digest from the record on your machine. If you get the same 64 characters as the page, you've reproduced the receipt.
Where the published files are¶
| file | address |
|---|---|
| the five receipts | habitat.ooo/receipts/ledger/receipts/receipt-<case>.json (edition 2 adds -e2) |
| the digests every receipt is checked against | habitat.ooo/digests.json, and digests-e2.json for edition 2 |
| the anchors, the keys and the verifier | habitat.ooo/receipts/anchors/ (the list is index.json) |
| the kits | by request; anchored by name |