Verify a single attestation against the daily T1 batch.
Every attestation registered through ExistBefore (free site or CertiSigma API) is bundled with thousands of others into a daily Merkle tree. The root of that tree — and only the root — is timestamped by an eIDAS-qualified TSA under Article 41 of Regulation 910/2014. This page lets you prove, in your own browser or with any RFC 6962 library, that a given attestation is one of the leaves of that signed batch.
The proof is small (a handful of 32-byte sibling hashes), the verifier is short (a few dozen lines), and the math is the same one used by Certificate Transparency to police the world's TLS certificates. No trust in ExistBefore or CertiSigma is required to perform the check.
Verify a proof in your browser.
Open the public proof page for any attestation, expand the Show batch inclusion proof panel, and copy the JSON shown below. Paste it here. The verification runs locally with WebCrypto — nothing transits to any server.
Verify with any RFC 6962 library.
You don't need to trust the JavaScript on this page. The proof format is RFC 6962 (Certificate Transparency) audit path with leaf prefix 0x00 and internal-node prefix 0x01. Any library that implements the standard will produce the same answer. Two minimal reference implementations follow.
Python (standard library only)
import hashlib
import json
def leaf_hash(b: bytes) -> bytes:
return hashlib.sha256(b'\x00' + b).digest()
def node_hash(left: bytes, right: bytes) -> bytes:
return hashlib.sha256(b'\x01' + left + right).digest()
def verify_inclusion(proof: dict) -> bool:
"""RFC 6962 inclusion proof verification."""
fn = proof['leafIndex']
sn = proof['treeSize'] - 1
if fn > sn or fn < 0:
return False
leaf_bytes = bytes.fromhex(proof['leaf'])
# If proof['leaf'] is already the leaf hash (32B), use it directly.
# Otherwise compute leaf_hash(leaf_bytes).
r = leaf_bytes if len(leaf_bytes) == 32 else leaf_hash(leaf_bytes)
for sibling_hex in proof['auditPath']:
sibling = bytes.fromhex(sibling_hex)
if sn == 0:
return False # path too long
if (fn & 1) or (fn == sn):
r = node_hash(sibling, r)
while not (fn & 1):
fn >>= 1
sn >>= 1
else:
r = node_hash(r, sibling)
fn >>= 1
sn >>= 1
if sn != 0:
return False # path too short
return r.hex() == proof['root']
# Usage:
proof = json.loads(open('proof.json').read())
print('VALID' if verify_inclusion(proof) else 'INVALID')
JavaScript (browser, WebCrypto, no dependencies)
async function sha256(bytes) {
return new Uint8Array(await crypto.subtle.digest('SHA-256', bytes));
}
const hex = (b) => [...b].map(x => x.toString(16).padStart(2, '0')).join('');
const unhex = (s) => new Uint8Array(s.match(/../g).map(b => parseInt(b, 16)));
async function leafHash(b) { return sha256(Uint8Array.of(0x00, ...b)); }
async function nodeHash(left, right) { return sha256(Uint8Array.of(0x01, ...left, ...right)); }
export async function verifyInclusion(proof) {
let fn = proof.leafIndex;
let sn = proof.treeSize - 1;
if (fn > sn || fn < 0) return false;
const leafBytes = unhex(proof.leaf);
let r = leafBytes.length === 32 ? leafBytes : await leafHash(leafBytes);
for (const siblingHex of proof.auditPath) {
const sibling = unhex(siblingHex);
if (sn === 0) return false;
if ((fn & 1) || fn === sn) {
r = await nodeHash(sibling, r);
while (!(fn & 1) && fn !== 0) { fn >>= 1; sn >>= 1; }
} else {
r = await nodeHash(r, sibling);
}
fn >>= 1;
sn >>= 1;
}
return sn === 0 && hex(r) === proof.root;
}
Both snippets are MIT-licensed; copy them into your audit toolkit. Either implementation, run against the JSON the proof page exports, must return the same boolean as this page.
What a positive verdict actually proves.
- The leaf is in the tree. The recomputed Merkle root matches the one declared by the batch — therefore the leaf is one of the
treeSizeleaves of that exact tree. Substituting any other leaf, or moving this leaf to a different index, would produce a different root. - The tree was sealed at a known time. The root is timestamped by an eIDAS-qualified TSA. The TSA's signed timestamp token is independently verifiable against EU trust lists.
- The proof is self-contained. It does not depend on ExistBefore or CertiSigma being online. Any party — auditor, court, journalist, regulator — with a copy of the audit path and the timestamp token can re-verify the chain forever.
What a positive verdict does not prove: that the original content has not been modified since the attestation was created (compare its current SHA-256 with the one in the certificate to check that), or that the file's content means what its filename suggests (semantics is out of scope; only the bytes are anchored).