← Course home Module 2 / 19 Blockchain — Part 1

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.

50 min Module 2 ₿ Part 1

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

1

Deterministic

Same input → same output. Always. On any machine, at any time.

2

One-Way (Pre-image Resistant)

Given a hash, it is computationally infeasible to find the original input. You can't run the grinder backwards.

3

Collision-Resistant

It is practically impossible to find two different inputs that produce the same hash. Each fingerprint is unique.

4

Avalanche Effect

Change one single bit of the input, and roughly half the output bits flip. The two hashes look completely unrelated.

5

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:

sha256-demo Terminal
$ 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

sha256-demo.js Node.js
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

keygen.js Node.js
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. Hash
Hash the message (e.g. a transaction) to produce a fixed-length digest.
2. Sign
Use your private key + the hash to produce a signature (two numbers: r and s).
3. Broadcast
Send the message + signature to the network. Your private key is never transmitted.
4. Verify
Anyone uses your public key + the message + the signature to check: was this really signed by the holder of this private key?

Three 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

sign-verify.js Node.js
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.

Merkle Root hash(H₁₂ + H₃₄)
H₁₂ hash(H₁ + H₂)
H₃₄ hash(H₃ + H₄)
H₁ TX₁
H₂ TX₂
H₃ TX₃
H₄ 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

merkle.js Node.js
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
Alice creates a transaction and signs it with her private key (ECDSA). She broadcasts the signed transaction to the network.
② Verifying
Every node verifies Alice's signature using her public key. Invalid signatures are rejected immediately — no wasted work.
③ Merkle Root
The miner collects valid transactions, builds a Merkle tree, and places the Merkle root in the block header.
④ Hash Chain
The block header also includes the hash of the previous block, creating an unbreakable chain. Changing any old transaction would invalidate every block after it.
⑤ Proof of Work
The miner hashes the block header billions of times, varying the nonce, until the hash starts with enough zeros. This is the "work" in proof-of-work (Module 1's HashCash idea).
Block #742,401
Prev Hash 0000000000000000000543a8…
Merkle Root 9b7c4d2e1f0a8b6c3d5e7f…
Timestamp 2024-01-15 08:32:17 UTC
Difficulty 72,006,525,080,335
Nonce 2,841,607,293
Block Hash 00000000000000000004a1b…
2,418 signed transactions → Merkle tree
🧩

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.

Node.js Download Node.js — nodejs.org
Docs Node.js Crypto docs — nodejs.org/api/crypto

Exercises

  1. 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"?
  2. 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)?
  3. Key pair: Generate an ECDSA key pair using secp256k1. Print both keys. How long is each one?
  4. 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?
  5. 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.

Next module

We combine all four tools to build a working cryptocurrency in Node.js: wallets, transactions, blocks, and a chain. From zero to a running blockchain.

Module 3: Build a Cryptocurrency →