DEV Community

Cover image for How Merkle Trees Verify Large Files
Doogal Simpson
Doogal Simpson

Posted on • Originally published at doogal.dev

How Merkle Trees Verify Large Files

Quick Answer: To verify massive files from untrusted sources, I use a Merkle tree. This cryptographic data structure chops the file into manageable chunks, hashes each one, and pairs them recursively into a pyramid. The final output is a single root hash that instantly alerts you if even one bit was altered.

Let's say you are torrenting. You are pulling down a massive 50-gigabyte file from hundreds of strangers across the internet. People you don't know are firing raw bits of data at your machine.

How do you know someone hasn't messed with it? How do you guarantee that a random peer didn't inject malicious code into one of those payloads?

You don't want to blindly trust the network, and you certainly don't want to wait until the entire 50GB is assembled on your hard drive to find out it is compromised. When I explain this concept to other engineers, I point them straight to Merkle trees.

What is a Merkle tree and how does it verify data integrity?

A Merkle tree is a tree-like data structure that uses cryptography to verify the contents of large datasets efficiently. It works by breaking a payload down into smaller chunks, hashing them, and combining those hashes recursively until a single root hash remains.

When you initiate the download for a massive file, the provider also hands you a 64-character hash. Hash functions are deterministic. They will always return the exact same output for the exact same input. More importantly, they are extremely sensitive to change. If you alter a single letter, or even flip a single bit in a 50GB file, the resulting hash completely changes.

How do you build a Merkle tree step-by-step?

You build a Merkle tree by dividing your large file into uniform blocks and running each one through a hash function. You then pair the resulting hashes, hash the pairs, and repeat this process layer by layer until you reach the top of the pyramid.

I find it easiest to visualize this as a literal pyramid built from the ground up:

  • Step 1: Chunk the file. Take your 50GB file and slice it into smaller pieces. Let's say we chop it into 1,000 distinct chunks.
  • Step 2: Hash the base layer. Run each of those 1,000 chunks through a cryptographic hash function. We now have 1,000 unique 64-character strings.
  • Step 3: Pair and hash. Take those 1,000 hashes, group them into pairs of two, and hash the combined pairs. The pile is reduced from 1,000 hashes down to 500.
  • Step 4: Repeat up the pyramid. Take those 500 hashes, pair them up, and hash the results to get 250.
  • Step 5: Extract the root hash. Continue this pairing-and-hashing loop until exactly one 64-character string remains at the very top.

What happens if someone tampers with the file during download?

If a malicious peer alters any part of the file, the hash of that specific chunk changes completely, which triggers a cascading mismatch all the way up the pyramid. The final root hash you calculate will not match the expected root hash you were originally given.

Imagine a scenario where someone tampers with the third chunk of your file. Because the input changed, the hash for chunk three changes. When you pair chunk three's new hash with chunk four's hash, their combined output changes. This chain reaction travels all the way up the tree.

When I finish running a Merkle tree over an assembled file, the top-level hash has to match the source of truth. If it looks entirely different from the one I was supposed to get, that mismatch is absolute proof that someone messed with the file.

Why use a Merkle tree instead of hashing the whole file at once?

Hashing a massive file all at once is inefficient because if the final hash fails, you have no way of knowing which specific part of the file is corrupted, forcing you to redownload the entire thing. Merkle trees isolate the exact location of the tampering, allowing you to reject and redownload only the corrupted chunks.

By using a tree structure, you can verify massive files at scale without having to process every single bit of the file simultaneously. You verify the integrity piece by piece as the chunks arrive.

FAQ

How do you fix a file if the Merkle tree root hash does not match?

When the root hash fails, your software doesn't throw away the whole file. It asks peers for the hashes of the branches directly below the root, traversing down the tree to isolate exactly which chunks caused the mismatch. You then delete only those specific bad chunks and redownload them.

Are Merkle trees only used for torrenting?

No. While they are heavily used in peer-to-peer file sharing, they are highly common across distributed systems. Git uses them to track file changes efficiently, and blockchain networks use them to verify blocks of transactions without needing to download the entire ledger.

Does a Merkle tree encrypt the file data?

No, a Merkle tree provides verification, not encryption. Hash functions are one-way cryptographic tools used to generate a unique fingerprint for the data. The actual contents of the 50GB file remain entirely unencrypted unless you separately apply an encryption algorithm to the payload.

Top comments (0)