Skip to content
habitat

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