ledger · trust anchor · ml-dsa-44

The ledger trust anchor

PCRZERO seals its usage ledger into daily checkpoints and signs each one. Every daily seal is then anchored on-chain, externally witnessed on Solana mainnet. The document to pin is the machine-readable one:

https://pcrzero.com/ledger/anchors.json

That path is a promise. It is meant to be hard-coded, so it will not move. Fetch it, check a signature against it, and you can verify the ledger without asking us anything — including long after we are not here to ask.

The anchor

kid
403bcd73e051e602b1b2e823f193c8d6e74aee8ed6cd37d524b8f82b7f89828c
algorithm
ML-DSA-44 (FIPS 204)
public key
1312 bytes, hex-encoded in the document
status
active
effective from
2026-08-08T00:00:00Z

The kid is a lookup handle, not evidence: it is sha256 over the raw public key bytes, so it recomputes from the key itself. A document claiming a kid proves nothing — the proof is a signature that checks out against the key you pinned.

Checking it

In a browser, or anywhere with the Web Crypto API. The document is served with Access-Control-Allow-Origin: * so a verifier on any origin can read it:

const url = 'https://pcrzero.com/ledger/anchors.json';
const doc = await (await fetch(url)).json();
const anchor = doc.anchors.find(
  (a) => (a.status ?? 'active') === 'active',
);

// the kid is a handle, not a proof — recompute it
// from the key you just fetched
const key = Uint8Array.from(
  anchor.ml_dsa_public_key.match(/../g),
  (h) => parseInt(h, 16),
);
const digest = await crypto.subtle.digest('SHA-256', key);
const kid = [...new Uint8Array(digest)]
  .map((b) => b.toString(16).padStart(2, '0'))
  .join('');

kid === anchor.kid;  // true — now verify a checkpoint

Re-fetch the document at least every 24 hours. It is served with Cache-Control: public, max-age=3600 and never longer, so a cached copy can never outlive a revocation by more than an hour.

The checkpoints

Every UTC day is sealed into a checkpoint: a canonical CBOR body carrying the period, the link to the seal before it, and the state root, signed with the key above. Each seal is published whole, at a path as stable as this one, and each is written into a Solana mainnet transaction whose memo is that checkpoint’s commitment.

The state below is read from the published packages themselves on every build, so a seal that is signed but not yet witnessed says so.

seqperiod (utc)anchor
42026-08-12confirmed31sbGTVL…cBbeybTA
32026-08-11confirmed5LUp4Caw…ppanuqZu
22026-08-10confirmed4G5GV6wJ…c9Axjkq2
12026-08-09confirmed2ijHBo33…24dGnrZp
02026-08-08confirmed5CssNBti…kWTzb8KT
witness

An anchor is a timestamp, not a verdict. The transaction records that a commitment existed by a certain block. It does not read the ledger, re-run any work, or examine a signature, and no chain ever inspects what PCRZERO measured. What makes a checkpoint valid is the ML-DSA signature over its body — and that holds with no chain and no network at all.

What the pin promises

rulewhat it means for a verifier
An anchor is never removedKeys are appended, newest last. A removed anchor is indistinguishable from one that never existed, which would break verification of everything it signed.
Status moves forward onlyactiveretiredrevoked. An absent status means active. The set is closed: adding a value is a version event, not a patch.
retired still verifiesRetirement ends a key’s authority to sign new periods. It never invalidates history — a checkpoint signed on day 100 must verify on day 10,000.
revoked repudiates signaturesIt impeaches a segment of a published record that does not rewrite, so it arrives as a published statement naming the affected periods — never as a quiet status change.
An unknown status is an errorThrow on it. Silently including trusts what you do not understand; silently dropping hides a partial set. A trust question is never guessed in either direction.
source

This document is a distribution fact, not a cryptographic one. It tells you which key to check against; the proof is still the signature over the checkpoint body. A verifier that trusts this document without checking signatures has verified nothing.

Why it is not self-signed

The anchor document is not signed by the key it names. A document signed by its own subject proves only that whoever holds the key wrote it, which is the thing in question. Its authority is this origin over HTTPS — and its history, which is public and does not rewrite.

Rotation

When a key is replaced, the new anchor is published as active with the first period it will sign, and the outgoing one moves to retired with its last — in a single update. A window where both read active, or neither does, is a window where you cannot tell who was authoritative.

The checkpoint chain continues across a rotation. Rotation changes the signer, never the chain: a restarted chain is indistinguishable from an equivocation.

If something does not verify

Tell us and we will treat it as an incident, not a support ticket: security.txt carries the contact. A failing verification against this anchor is either our defect or our compromise, and both are ours to answer for.