What you'll be able to do
- Build a Merkle tree and explain what its root commits to.
- Generate and verify an inclusion proof by hand β and say why it's only
βlogβ nβhashes. - Explain where the trusted root must come from, and why a proof without that is worthless.
- Break two real constructions: the second-preimage forgery (no domain separation) and CVE-2012-2459 (odd-node duplication).
- Verify a consistency proof and state exactly what "append-only" does and doesn't guarantee.
- Verify a real Certificate Transparency entry β production data, in this page, offline.
1 Β· What is a Merkle Tree?
A Merkle tree is a binary tree of hashes. Each leaf holds the hash of one data block; each internal node holds the hash of its two children concatenated. The single hash at the top β the root β commits to every leaf at once: change any byte of any block and the root changes.
This demo uses real SHA-256 via the browser's WebCrypto API, with RFC 6962 domain separation:
leaf hash = SHA-256(0x00 β₯ data)node hash = SHA-256(0x01 β₯ left β₯ right)
A small 4-leaf tree (leaf order is left to right; the root sits on top):
2 Β· Build a Tree
Add or remove data blocks. The tree (and its root) rebuilds live. Click any leaf to select it for a proof.
3 Β· Generate a Proof
An inclusion proof (audit path) is the minimal set of sibling hashes needed to recompute the root from one leaf. Pick a leaf below (or tap one in the tree above) to highlight its proof.
- selected leaf
- proof (sibling) hash β the only hashes a verifier receives
- recomputed path to the root
4 Β· Verify a Proof
A verifier recomputes the root from only the leaf and the proof, then checks it against the trusted root. Try tampering β the verdict flips to REJECTED the moment anything changes.
You flip one bit of a single sibling hash deep in the proof. Will verification still pass?
No. That bit changes the parent hash, which changes its parent, all the way up β the recomputed root no longer matches. One bit anywhere in the leaf or proof is enough to break it. This is the avalanche property of SHA-256 plus the tree's hash chaining.
Proof steps (editable)
Each row is one sibling hash. Flip a bit to see verification fail.
Recomputation trace
The verifier recomputes the root from the leaf up. Expand βshow bytesβ on any line to see the exact input to SHA-256 β leaves are 0x00 β₯ data, nodes are 0x01 β₯ left β₯ right.
Where does the trusted root come from?
Everything above assumed the verifier already holds the right root. That assumption is the entire security model. A proof only ties a leaf to some root β if the person making the claim also hands you the root, they can build a tree around any lie.
Mallory invents a fake transaction, builds her own Merkle tree around it, and sends you the leaf, the proof, and the root. Does verification pass?
Yes β perfectly. The hashes are all real SHA-256 and all self-consistent. Verification can never tell you the root is the agreed-upon one; only the channel that delivered the root can. That's why Bitcoin roots live in mined block headers and CT roots come as signed tree heads that clients gossip and compare.
Self-check
5 Β· Why It Scales (Logarithmic Proofs)
Proof size grows with the height of the tree, not its width β that's βlogβ nβ hashes for n leaves. Drag to see how a proof stays tiny even as the dataset explodes.
Prove it on a real tree
Build an actual SHA-256 tree in your browser and verify a proof against it β no shortcuts.
In the wild: a Bitcoin block with ~3,000 transactions (~1.5 MB) needs a 12-hash proof β 384 bytes β for an SPV wallet to confirm a payment. Certificate Transparency logs hold billions of certificates and still prove any one of them in 32 hashes β 1 KB β you'll verify a real one in section 8.
Self-check
6 Β· Security: Why the 0x00 / 0x01 Prefixes Matter
Without domain separation, a leaf is hashed exactly like an internal node β so an attacker can take an internal node's two child hashes, glue them into a 64-byte "leaf", and prove inclusion of a leaf that never existed. This is the classic second-preimage (leaf-node confusion) attack. RFC 6962's 0x00/0x01 prefixes put leaf and node hashes in separate spaces and shut it down.
Turn the toggle off to see the forgery accepted (vulnerable), then back on to see it rejected. The main builder above always keeps domain separation on.
A second pitfall: odd-node handling (CVE-2012-2459)
When a level has an odd number of nodes, something must be done with the lone node. Bitcoin duplicated it (hash(x β₯ x)), which let an attacker pad a block's transaction list with a repeated last transaction to get the same Merkle root β mutating blocks and splitting the network. RFC 6962 promotes the lone node unchanged, which has no such collision.
Self-check
7 Β· Consistency (Append-Only) Proofs
Everything above proves inclusion β that one leaf is in the tree. A consistency proof answers a different question that logs care about: is the old tree of size m an exact prefix of the new tree of size n β i.e. did the log only append, never rewrite history? This is the guarantee Certificate Transparency is built on.
Why it works: the old root is stitched together from a few complete subtrees β and those exact subtrees still sit, byte-for-byte, inside the new tree. The proof hands the auditor just enough subtree roots to rebuild both the remembered old root and the claimed new root. If the same handful of hashes can reproduce both, nothing before entry m changed.
The log (a growing list of certificates; shaded = the old size-m prefix):
- the old size-m tree (shaded prefix)
- proof hash inside the prefix β rebuilds the old root, then reused for the new one
- proof hash in the appended region β completes the new root
The log operator deletes one early entry but keeps appending, so the log is still growing. Will the consistency proof still verify?
No. "Append-only" means every old entry must stay at its exact position. A deletion shifts every later leaf one slot left, which changes every subtree containing them β the remembered old root can no longer be rebuilt from the new tree's subtrees. Same for reordering: same contents, different positions, different hashes. Try both below.
Every attack keeps the auditor's remembered old root but alters the log the operator presents β the consistency proof then fails, exposing the tampering. Entries marked β are where the presented log differs from the original. Honest limit: tampering is only caught if it touches entries the old root committed to (positions < m) β a change entirely after position m is invisible to this old root, which is why auditors keep requesting fresh signed tree heads.
Self-check
8 Β· Verify a REAL Certificate Transparency Entry
Everything so far used toy data. This section uses none. Below is a real entry from Google's Argon2026h1 CT log β a Let's Encrypt certificate that actually protects a real website β together with the real audit path the log served, pinned so it verifies offline forever. The verifier here is the same RFC 6962 construction you've been stepping through: SHA-256(0x00 β₯ leaf), SHA-256(0x01 β₯ L β₯ R).
One production difference: a real log doesn't send left/right flags with the proof. The verifier derives each side from the entry's index and the tree size by walking the index's bits (RFC 9162 Β§2.1.3.2) β expand the steps below to see the derived sides.
In production the verifier also checks the log's ECDSA signature over the tree head (the signed tree head); here that head is pinned into the page instead. The tree had 2,807,499,968 certificates when fetched β and one flipped bit anywhere in this 1,033-byte certificate entry still breaks all 32 hashes above it.
9 Β· Where Merkle Proofs Are Used
Bitcoin & Ethereum
Block headers commit to a Merkle root of all transactions. An SPV / light client proves a transaction is in a block with a short branch β no need to download the full chain. Caveat if you try this at home: Bitcoin's construction differs from this lab's β double SHA-256, byte-reversed txids, no domain separation (hence section 6's CVE), so its roots won't match an RFC 6962 tree.
Git
Every commit, tree, and blob is content-addressed by hash, forming a Merkle DAG. The commit hash pins the entire history; any tampering changes every descendant hash.
Certificate Transparency
CT logs (RFC 6962 β the exact construction here) publish a Merkle root so anyone can prove a certificate was logged and that the log is append-only. Section 8 verifies a real entry from a live log.
Stateless / light clients
Merkle (and Verkle) proofs let a client check that an account balance or state value is part of a committed root without holding the whole state tree.
10 Β· Recap: The Two Proofs, Side by Side
| Inclusion proof (Β§3β4) | Consistency proof (Β§7) | |
|---|---|---|
| Question answered | "Is this leaf in the tree?" | "Is the old tree an untouched prefix of the new one?" |
| Verifier holds | the leaf + the trusted root | the old root + the new root |
| Prover sends | sibling hashes up the leaf's path | the subtree roots that rebuild both roots |
| Size | βlogβ nβ hashes | β logβ n hashes |
| Who runs it | light clients, SPV wallets, browsers | log auditors and monitors |
| What it can NOT prove | absence, order, or that the root is the agreed-upon one (Β§4) | that entries are valid, or that any specific entry is present |
Test yourself (no peeking)
- Sketch a 4-leaf tree from memory and mark exactly which hashes a proof for leaf 2 contains.
- Explain to a rubber duck why the 0x00/0x01 prefixes are load-bearing and not decoration.
- State the one thing verification can never tell you about the root β and where real systems get it instead.
- Say what breaks if a log deletes an entry, in terms of leaf positions and subtree hashes.
Further reading
- Merkle 1979 β Secrecy, Authentication, and Public Key Systems (Ch. 5 introduces "tree authentication" β this whole page in ~10 pages of 1979 typewriter)
- RFC 6962 β Certificate Transparency (Β§2.1 is the exact construction this lab implements) and its successor RFC 9162 (Β§2.1.3.2/Β§2.1.4.2 are the verification algorithms used here)
- Nakamoto 2008 β Bitcoin whitepaper (Β§7β8: Merkle trees for block compaction and SPV)
- How CT works β certificate.transparency.dev (the ecosystem around the math: logs, monitors, gossip)
- CVE-2012-2459 (the odd-node duplication bug you reproduced in section 6)