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. | 96f3484f013822cb810f101f3d12ba22a3bfb3b2fd5aa5fa7351df1bc3cead9a 68,442 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. | 611682fc7008830a2fab6ad2cc03314d9b9dab77db0b5dbf89441a6d0468a361 50,808 bytes |
| verifybundle-conformance-vectors.zip The golden conformance vectors (v1 Ed25519, the v2 hybrid ML-DSA-65 + Ed25519, and the v2 time-bound vector pinning the content-bound time attestation), so an independent re-implementation can prove it agrees on frozen bytes. | 4f3c8f2968a5a23124ba87b27e2c06abe60330ce5fff1080775a5bddd2d2bb49 59,554 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 96f3484f…. 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