The Cryptographic Toolkit
Four tools underpin every blockchain: hash functions, public-key cryptography, digital signatures, and Merkle trees. Master them here — with real Node.js code.
Why Cryptography?
In Module 1, you saw 30 years of failed digital money. Every attempt relied on a set of mathematical tools most people never think about. In this module we open the toolbox and examine each tool one by one — so that when we build a cryptocurrency in Module 3, you'll understand exactly why each piece is there.
The Four Tools
Every blockchain — Bitcoin, Ethereum, enterprise chains — relies on the same four cryptographic primitives. Think of them as the screwdriver, hammer, saw, and measuring tape of the crypto world. None of them is new; they were all invented decades before Bitcoin. Satoshi's genius was combining them.
Hash Functions
A fingerprint machine. Feed any data in, get a fixed-size digest out. Impossible to reverse.
Asymmetric Keys
A pair: one public (your address), one private (your password). Mathematically linked, but you can't derive the private key from the public one.
Digital Signatures
Proof that the owner of a private key approved a message — without revealing the key itself.
Merkle Trees
A data structure that lets you verify thousands of transactions with a single hash.
Hash Functions
A hash function takes any input — a word, a book, an entire database — and produces a fixed-length output called a digest (or simply a hash). SHA-256, the algorithm Bitcoin uses, always outputs exactly 256 bits (64 hex characters), no matter the input size.
The Meat-Grinder Analogy
Think of a hash function like an industrial meat grinder. You can feed in a steak (any data), and it produces mince (the hash). But you can never reconstruct the steak from the mince. And if you grind the exact same steak twice, you get exactly the same mince every time.
Five Essential Properties
Deterministic
Same input → same output. Always. On any machine, at any time.
One-Way (Pre-image Resistant)
Given a hash, it is computationally infeasible to find the original input. You can't run the grinder backwards.
Collision-Resistant
It is practically impossible to find two different inputs that produce the same hash. Each fingerprint is unique.
Avalanche Effect
Change one single bit of the input, and roughly half the output bits flip. The two hashes look completely unrelated.
Fixed Size
Whether you hash "Hi" or the entire Wikipedia, the output is always exactly 256 bits (for SHA-256).
See the Avalanche Effect
Notice how changing just one letter (lowercase "b" → uppercase "B") completely transforms the hash:
$ echo -n "blockchain" | sha256sum
ef7797e13d3a75526946a3bcf00daec9fc9c9c4d51ddc7cc5df888f74dd434d1
$ echo -n "Blockchain" | sha256sum # capital B
625da44e4eaf58d61cf048d168aa6f5e492dea166d8bb54f06c3b1f4a001be23
One letter changed, every character in the hash is different. That's the avalanche effect in action.
Node.js: Your First Hash
const { createHash } = require('crypto');
function sha256(data) {
return createHash('sha256')
.update(data)
.digest('hex');
}
console.log(sha256('blockchain'));
// ef7797e13d3a75526946a3bcf00daec9fc9c9c4d51ddc7cc5df888f74dd434d1
console.log(sha256('Blockchain'));
// 625da44e4eaf58d61cf048d168aa6f5e492dea166d8bb54f06c3b1f4a001be23
Why Hashing Matters for Blockchain
Hashing is used everywhere in a blockchain: linking blocks together (each block header includes the hash of the previous block), mining (finding a hash that starts with enough zeros), verifying data integrity (if even one byte is changed, the hash is completely different), and — as we'll see shortly — building Merkle trees.
Asymmetric Key Cryptography
Symmetric cryptography uses one key for both locking and unlocking — like a door key. The problem: how do you share that key securely with a stranger on the internet? Asymmetric cryptography solves this by using two keys: one public, one private.
How can Alice prove she owns a Bitcoin address without showing anyone her private key?
The Mailbox Analogy
Your public key is like the slot on a mailbox: anyone can drop a letter in. Your private key is the key to the mailbox: only you can open it and read the letters. Everybody knows your address (public key), but only you control what happens with the contents (private key).
Public key
- Derived from the private key (one-way)
- Shared freely — it's your "address"
- Used to verify signatures and encrypt messages
Private key
- A random 256-bit number — keep it SECRET
- Never shared — losing it means losing your coins
- Used to create signatures and decrypt messages
ECDSA — Bitcoin's Chosen Algorithm
Bitcoin uses the Elliptic Curve Digital Signature Algorithm (ECDSA) with a specific curve called secp256k1. The maths behind it is elegant: multiplying a point on the curve by a large number (your private key) is fast, but reversing the operation (finding the private key from the public point) would take longer than the age of the universe.
Node.js: Generate a Key Pair
const { generateKeyPairSync } = require('crypto');
const { publicKey, privateKey } = generateKeyPairSync('ec', {
namedCurve: 'secp256k1',
publicKeyEncoding: { type: 'spki', format: 'pem' },
privateKeyEncoding: { type: 'pkcs8', format: 'pem' },
});
console.log('Public key:\n', publicKey);
console.log('Private key:\n', privateKey);
Rule #1 of Crypto: Never Lose Your Private Key
There is no "forgot password" button. If you lose your private key, your coins are gone forever — no bank, no customer support, no recovery. This is both the power and the danger of decentralised systems. "Not your keys, not your coins."
Digital Signatures
A digital signature is the bridge between your private key and the outside world. It lets you prove "I authorised this transaction" without revealing your private key. Anyone with your public key can verify the signature — but nobody can forge one without the private key.
The Sign → Verify Cycle
1. Hash2. Sign3. Broadcast4. VerifyThree Guarantees
Authentication — the signer is who they claim to be. Integrity — the message was not altered after signing. Non-repudiation — the signer cannot deny having signed. These three properties are the foundation of trustless transactions in blockchain.
Node.js: Sign and Verify a Message
const { createSign, createVerify, generateKeyPairSync } =
require('crypto');
// 1. Generate key pair
const { publicKey, privateKey } = generateKeyPairSync('ec', {
namedCurve: 'secp256k1',
});
// 2. Sign
const message = 'Alice sends 1 BTC to Bob';
const signer = createSign('SHA256');
signer.update(message);
const signature = signer.sign(privateKey, 'hex');
// 3. Verify
const verifier = createVerify('SHA256');
verifier.update(message);
console.log(verifier.verify(publicKey, signature, 'hex'));
// true ✓
Signatures in Bitcoin
Every Bitcoin transaction includes one or more digital signatures. When you "send Bitcoin", you're really signing a message that says "I, the owner of this private key, authorise transferring X BTC to this address." Miners and nodes verify these signatures before including the transaction in a block.
Merkle Trees
A Bitcoin block can contain thousands of transactions. Verifying all of them one by one is slow. Ralph Merkle (1979) invented a data structure that lets you verify any single transaction using only a handful of hashes — even in a block with 10,000 transactions.
Building a Merkle Tree
Start with four transactions: TX₁, TX₂, TX₃, TX₄. Hash each one individually. Then pair them up and hash each pair: H₁₂ = hash(H₁ + H₂), H₃₄ = hash(H₃ + H₄). Finally, hash the pair of pairs: Merkle Root = hash(H₁₂ + H₃₄). The result is a single hash that represents all four transactions.
hash(H₁₂ + H₃₄)
hash(H₁ + H₂)
hash(H₃ + H₄)
TX₁
TX₂
TX₃
TX₄
Merkle Proof (inclusion proof)
- To prove TX₃ is in the block, you only need H₄ and H₁₂
- Compute: H₃ = hash(TX₃), H₃₄ = hash(H₃ + H₄), Root = hash(H₁₂ + H₃₄)
- If the computed root matches the block's Merkle Root → TX₃ is verified
Why it's efficient
- 1,000 TXs → only ~10 hashes needed (log₂ 1,000)
- 1,000,000 TXs → only ~20 hashes needed
- Light clients (mobile wallets) use this to verify without downloading the full blockchain
Node.js: Build a Merkle Root
const { createHash } = require('crypto');
function sha256(data) {
return createHash('sha256').update(data).digest('hex');
}
function merkleRoot(txs) {
let hashes = txs.map(tx => sha256(tx));
while (hashes.length > 1) {
if (hashes.length % 2) hashes.push(hashes[hashes.length - 1]);
const next = [];
for (let i = 0; i < hashes.length; i += 2)
next.push(sha256(hashes[i] + hashes[i + 1]));
hashes = next;
}
return hashes[0];
}
const txs = ['Alice→Bob 1BTC', 'Bob→Carol 0.5BTC',
'Carol→Dave 0.3BTC', 'Dave→Eve 0.1BTC'];
console.log('Merkle root:', merkleRoot(txs));
SPV: Simplified Payment Verification
Satoshi described SPV in the white paper (Section 8). A mobile wallet doesn't download the entire blockchain (~500 GB). Instead, it downloads only block headers (80 bytes each) and uses Merkle proofs to verify that a specific transaction is included in a block. This is why Merkle trees are essential — they make lightweight verification possible.
Putting It All Together
Each tool is powerful on its own. But Bitcoin's strength comes from combining all four into a single, interconnected system. Let's trace how they work together inside a single Bitcoin block.
Inside a Bitcoin Block
① Signing② Verifying③ Merkle Root④ Hash Chain⑤ Proof of Work0000000000000000000543a8…
9b7c4d2e1f0a8b6c3d5e7f…
2024-01-15 08:32:17 UTC
72,006,525,080,335
2,841,607,293
00000000000000000004a1b…
Tamper-Evident by Design
Change one transaction → the Merkle root changes → the block hash changes → the next block's "previous hash" field no longer matches → every subsequent block is invalid. An attacker would need to redo the proof-of-work for every block from the tampered one forward — while the rest of the network keeps building. The cost is astronomical.
Exercise: Crypto Toolkit in Node.js
Time to get your hands dirty. These exercises bring together everything from this module: you'll hash data, generate keys, sign transactions, and build a Merkle tree — all in a few lines of Node.js.
Your Tasks
Open a terminal with Node.js installed (v16+). Create a new file for each exercise. All you need is the built-in crypto module — no npm packages required.
Exercises
- Hash explorer: Write a function that takes a string and prints its SHA-256, SHA-512, and MD5 hashes. Hash your own name. Do all three look equally "random"?
- Avalanche test: Hash "Hello" and "hello" with SHA-256. Count how many hex characters differ between the two outputs. Is it close to half (32 out of 64)?
- Key pair: Generate an ECDSA key pair using secp256k1. Print both keys. How long is each one?
- Sign & verify: Sign the message "I owe you 1 BTC" with your private key. Verify it with the public key. Then change the message to "I owe you 100 BTC" and try to verify again with the same signature. What happens?
- Merkle root: Implement the
merkleRoot()function from Section 5. Test it with 3, 4, and 7 transactions. What happens when the number of transactions is odd?
Module Summary
You now have the four core tools of blockchain cryptography in your toolkit. In the next module, we'll use them to build an actual cryptocurrency from scratch — complete with wallets, transactions, blocks, and a chain.