Reading a receipt

Every verdict Turiya issues is signed and content-addressed. This page explains what the words mean and how to check one without trusting us.

The verdict lattice

A verdict is never “true”. Verification is asymmetric: you can falsify a claim, you can never prove one.

VerdictMeans
falsifiedThe claim was tested and did not hold.
not_falsifiedThe claim survived the testing performed. Not a statement that it is true.
certifiedA formal specification was checked, and the output carries its proof.
indeterminateWe decline to rule. A refusal to bless, not a failure to decide.

indeterminate is a real answer. When a claim is shaped so that no honest test settles it, we say so rather than pick a side. That will lose us deals with buyers who want a rubber stamp. It is the reason the other three verdicts are worth anything.

What the signature proves

Each receipt carries:

  • a content address: record_hash, the SHA-256 of the canonical record. Change one byte anywhere in the record and the hash changes.
  • an Ed25519 signature over that hash.
  • the key id that signed it, and, when an everyday key signed, a certificate from our offline master key showing that key was authorised at that time.
  • an RFC 3161 timestamp from an independent Time-Stamp Authority, over the same hash.

The timestamp exists because the record already contains a signed_at field, and that field is our claim. We set it, and we sign it — which proves nobody changed it afterwards, and proves nothing about whether we picked the right date. Whoever holds a signing key could date a receipt whenever they liked, and it would still verify.

The timestamp token is signed by the TSA, not by us, so its time comes from outside. That matters most for key rotation: a receipt signed while a key was valid stays valid after that key expires, and the timestamp is what makes that claim checkable rather than asserted.

It also lets you verify without us. The token is a standard CMS blob and the TSA’s certificate travels inside the receipt, so openssl ts -verify is enough.

The signature proves the record was issued by the holder of a key we authorised, and that it has not been altered since. It does not prove the record is right; that is what re-running the verification is for.

Verify one yourself

Every receipt page on the public board has a verify button. It runs entirely in your browser:

  1. Re-derives the content address from the record and checks it matches.
  2. Checks the Ed25519 signature against the published public key.
  3. Checks the master-key certificate, when one is present.
  4. Compares the numbers shown on the page against the signed set.

The RFC 3161 timestamp is not checked in the browser, and we are not going to pretend it is. Verifying a CMS token means ASN.1 parsing, and reimplementing that in a web page is how you get a green tick that means nothing. The receipt carries the token and the TSA’s certificate, and one command checks it properly:

openssl ts -verify -in token.tsr -digest <record_hash> -CAfile ca.pem

The site’s own build runs an equivalent check over every published receipt, and the test suite fails if any of them stops verifying.

No request goes to us. You can read the source in the page and run the same check offline.

You can also fetch the raw receipt and check it with your own tooling. It is served verbatim:

/receipts/<id>.json

If a receipt fails to verify

Check these in order:

  • The record was modified. Receipts are content-addressed, so any change to any field breaks the hash. This is the intended behaviour, not a bug.
  • You are checking against the wrong key. Each receipt names its key id. A receipt signed by a retired key still verifies against the key that was in force when it was signed, which is why the signing timestamp lives inside the signed payload.
  • Your browser lacks Ed25519. WebCrypto supports it in current browsers. If the check cannot run, it says so rather than reporting a pass or a fail.

Retirement notices

If a signing key is ever compromised or retired, the disownment notice is signed by the master key, never by the key being retired, and published at /keys/retirements.json. A notice signed by the key it disowns would prove nothing: whoever held the key could sign one just as convincingly.

Receipts signed before a compromise keep verifying. We cannot un-publish, and we never re-sign a published receipt to change its wording.

Ready to scope an engagement?

START WITH A PILOT