The format, published and pinned.
A VerifyBundle record is meant to be checked without trusting us. Everything needed to do that is published here: the offline verifier, the specification, and the conformance vectors. Each is pinned by a SHA-256 so you can confirm the file you hold is the exact one published, before you trust it to verify anything.
The hash is the point. Download an artifact from here or from anywhere it is mirrored, check its SHA-256 against the trust root below, and the source no longer matters. Verification is in-browser math over the bundle bytes: Ed25519 (RFC 8032) and SHA-256 (FIPS 180-4) for v1 records, plus ML-DSA-65 (FIPS 204) for the v2 post-quantum hybrid.
The artifacts, and their trust roots
Three files. The SHA-256 beside each is its trust root: recompute it after downloading and confirm it matches. If it differs, do not trust the file.
| Artifact | SHA-256 (trust root) · size |
|---|---|
| verifier.html The offline verifier: one self-contained HTML file. Open it directly, with the network off, and verify any record. No server, no account, no network. | 2f593ef91e8f5d7c0104240858cce7060038e35612987a07d5b1c8c7d456835a 65,642 bytes |
| VERIFYBUNDLE_SPEC.md The normative specification: the bundle and seal format, the canonicalization, the Merkle and checkpoint construction, and the verification rules. Enough to re-implement the verifier from scratch. | 89a4221951e20a318be930d5c91df881ffbe694bfa70d3ee4b0bc77a10b67569 43,485 bytes |
| verifybundle-conformance-vectors.zip The golden conformance vectors (v1 Ed25519, and the v2 hybrid ML-DSA-65 + Ed25519), pinning the expected bytes so an independent re-implementation can prove it agrees. | ddc9a78ee5f2c91350412f6b3170e32565f14527298b06344744cbf151e876d7 13,419 bytes |
Verify a record yourself
Trust nothing we serve. This is exactly what a stranger does.
- Download verifier.html from the table above.
- Compute its SHA-256 and confirm it equals the trust root 2f593ef9…. If it differs, do not trust it.sha256sum verifier.htmlshasum -a 256 verifier.htmlcertutil -hashfile verifier.html SHA256
- Open the file directly (double-click, so it loads over file://), with the network disconnected.
- Drop in a .vbundle (or paste its bundle.json). A valid record shows VERIFIED; a tampered one shows FAILED. No server, no account, and no network involved.
The verifier carries a Content-Security-Policy of connect-src 'none', so the browser blocks any network call at runtime, not merely in the source. It is one self-contained file: everything it runs is in the bytes you just hash-checked, and the open specification below is enough to re-implement it from scratch.
Re-implement the verifier from scratch
You do not have to use our verifier at all. Follow the specification and check your implementation against the conformance vectors, which pin the expected bytes for both signature profiles.
The proof commits to a hash of your data, not the data
A record's verifiable structure (the signed receipt, the Merkle leaf, and the signed checkpoint) is computed over the record's structural metadata: the hash of your content, the field labels, the timestamps. Your content itself is referenced only by its SHA-256 and never enters that structure. This is a deliberate design choice, and it has two consequences worth stating plainly.
- The proof travels without the data. A record can be checked by anyone to confirm the content is unchanged, without the content ever being shown. You disclose the proof; you need not disclose what it covers.
- It survives a public log. Because no content sits inside the verifiable structure, a record's proof could be published to a public transparency log to show it existed at a time, and still not expose the sealed content, only a hash of it. A construction that put the content inside the logged structure would expose it there; this one keeps the content out of it.
This is one property among several, not a guarantee on its own. Paired with the canonicalization, the signed checkpoint, and the offline verifier above, it is part of what lets a record be both portable and private. The exact construction is in the specification.
Verification does not depend on this site staying up. A copy of the verifier you already hold keeps checking records offline, on your own device, even if this site is gone; and the spec is open, so the verifier can be re-implemented from it and proven against the conformance vectors. Wherever you obtain a copy of an artifact, the trust root above is what you check it against: it is always the current one.
ML-DSA-65 · FIPS 204 · Ed25519 · RFC 8032 · SHA-256 · FIPS 180-4