Chapter 12 of Trappe & Washington: the birthday paradox derived from the book's own numbers and turned into the 2^(n/2) collision bound that sets digest, block, nonce and group sizes; Joux's multicollisions and why concatenating two hashes buys almost nothing; the random oracle model; hash-based stream encryption; HMAC and precisely which attack its outer hash prevents; password protocols and their three separate failures; and hash pointers, Merkle trees and blockchains, together with the agreement problem hashing cannot solve.
Subject: Cryptography · 60 slides · diagram-first lesson
Open the interactive version of this deck
Title
Cryptography · Chapter 12
The birthday attack, multicollisions, HMAC, password protocols, and the hash chains behind blockchains
Objectives
Chapter 11 built the primitive and quoted a security level of 2^(n/2) against collisions. This chapter derives that number, shows a case where even it is optimistic, and then spends its length on what hash functions are actually for.
Figure (svg): The probability of a shared birthday rising steeply with the number of people, crossing one half at twenty-three.
Warm-up
Chapter 11 said an n-bit hash gives n bits against preimages and n/2 against collisions.
Discussion prompt
Why should finding any colliding pair be so much easier than hitting a given digest?
Hint: Count how many chances the attacker gets in each case.
Answer:
Hitting a given digest gives one chance per try. Each guess either matches the target or does not, so after k guesses you have had k chances out of 2ⁿ.
**Finding any collision gives a chance per pair.** After k guesses there are k(k−1)/2 ≈ k²/2 pairs, each of which might collide. So the number of opportunities grows quadratically while the effort grows linearly.
Setting k²/2 ≈ 2ⁿ gives k ≈ 2^(n/2) — the square root, and the factor of two in the exponent.
The same arithmetic explains the birthday paradox: 23 people give 253 pairs against 365 days, which is why the probability is already about even. The counter-intuitive part is entirely about counting pairs rather than people.
Figure (svg): Why the birthday bound is a square root: the number of pairs among k items grows as k squared over two.
Section
Section 12.1 · pp. 246-249
Concept
With 23 people in a room, the probability that two share a birthday is slightly over 50%. With 30 it is about 70%, and with 40 it is 89%. The book calls this the birthday paradox, though nothing about it is contradictory once the pairs are counted.
Compute the probability that all 23 birthdays differ. The second person must avoid one day, the third must avoid two, and so on:
\[ \left(1 - \tfrac{1}{365}\right)\left(1 - \tfrac{2}{365}\right)\cdots\left(1 - \tfrac{22}{365}\right) = 0.493 \]
So the probability of a match is 1 − 0.493 = 0.507.
The book's intuition for the 40-person case is worth keeping: if the first 30 have no match, there are already 30 days taken, so each of the remaining 10 people has about a 10% chance of hitting one. Ten people at roughly 10% each makes a match unsurprising.
Figure (svg): The probability of a shared birthday rising steeply with the number of people, crossing one half at twenty-three.
Worked example
Replace 365 days with 2ⁿ digests and the calculation carries over unchanged.
Compute k hash values of random inputs
Why: Each one is, to the extent the hash is good, a uniformly random n-bit string.
There are k(k−1)/2 ≈ k²/2 pairs, and each collides with probability 2⁻ⁿ
Why: Assuming independence, which is the right first approximation for a well-designed hash.
The expected number of collisions is about k²/(2 · 2ⁿ)
Why: Set this to 1 to find where a collision becomes likely.
\[ k \approx 2^{n/2} \]
Verify: apply it to SHA-256: k ≈ 2¹²⁸
Why: Which is Chapter 11's quoted figure. And to SHA-1's 160 bits: 2⁸⁰, which is the number the 2017 attack undercut. The bound is generic — it assumes nothing about the function beyond its output length, so no design can beat it, and cryptanalysis can only make things worse.
Figure (svg): Why the birthday bound is a square root: the number of pairs among k items grows as k squared over two.
Concept
The abstract bound becomes a concrete forgery. Suppose Eve wants Alice's signature on a fraudulent contract.
Alice signed a document she read and approved. The signature is valid on a document she never saw, because signatures cover the digest and the two documents have the same one.
This is why signature schemes need collision resistance rather than preimage resistance: Eve chose both documents. And it is why finding slack bytes is easy — every real document format has places where arbitrary content is ignored.
Figure (svg): The birthday attack on signatures: two large sets of document variants, matched until one pair collides.
Estimation
A signature scheme hashes with a 128-bit function before signing.
Predict first
Roughly how many document variants must Eve prepare for the birthday attack?
Correct: 2⁶⁴
It is also why MD5, at 128 bits, was retired from signing long before its cryptanalytic weaknesses were found — the generic bound alone was too close.
The storage requirement was once the practical limit, but memoryless collision search — Pollard's rho, applied to hashing — achieves the same 2^(n/2) time with negligible memory, so storage is not a defence.
Why: About 2⁶⁴ of each kind, by the birthday bound. That is around 18 quintillion — large, but within reach of a determined adversary with storage, and far below the 2¹²⁸ the digest length suggests. It is precisely why a 128-bit hash is inadequate for signatures while remaining fine for a checksum.
Figure (svg): The probability of a shared birthday rising steeply with the number of people, crossing one half at twenty-three.
Real world
The same bound applies wherever an attacker collects samples and waits for a repeat.
Discussion prompt
Name three other places in this course where 2^(n/2) is the operative number.
Hint: One is a block cipher's block size, one is a discrete logarithm, one is a mode's nonce.
Answer:
Block size. With a 64-bit block, a repeated ciphertext block becomes likely after 2³² blocks — 32 GB. In CBC mode a repeat reveals the XOR of two plaintext blocks, which is the Sweet32 attack that retired triple DES.
Discrete logarithms. Section 10.2's baby step giant step costs √N, and Pollard's rho achieves the same with no storage. Both are birthday arguments in a group.
Nonces and IVs. A random 96-bit nonce repeats after about 2⁴⁸ messages, which is why GCM's specification bounds the number of messages per key. WEP's 24-bit IV repeats after 2¹² — a few thousand packets — which is Chapter 14's subject.
The unifying statement: any n-bit value chosen repeatedly at random will repeat after about 2^(n/2) draws. Wherever a design says 'this value must be unique', ask how many will be drawn and compare with the square root of the space.
Section
Section 12.2 · pp. 249-251
Concept
Generalise the birthday bound. With N possible values, about N^((k−1)/k) samples give a good chance of k of them agreeing. For a hash with n-bit outputs that means a k-collision should cost 2^(n(k−1)/k) — for k = 4, about 2^(3n/4).
Joux showed that Merkle-Damgård hashes do far worse than this, and the reason is entirely structural.
Total cost: t · 2^(n/2) for a 2^t-collision, where the generic bound predicts 2^(n(2^t−1)/2^t). The cost is linear in t and the payoff exponential.
Figure (svg): Joux's multicollision: t successive two-way collisions in a Merkle-Damgard chain give two to the t colliding messages.
Worked example
A natural defence: use H(m) = H₁(m) ‖ H₂(m), with two different hash functions. The digest is n₁ + n₂ bits, so collisions should cost 2^((n₁+n₂)/2).
Build a 2^t-multicollision on H₁ alone, at cost t · 2^(n₁/2)
Why: Joux's construction. All 2^t of these messages have the same H₁ digest.
Now hash all 2^t of them under H₂ and look for a collision there
Why: Within a set that already collides under H₁.
Choose t = n₂/2, so the set has 2^(n₂/2) members — enough for a birthday collision under H₂
Why: The total cost is about (n₂/2) · 2^(n₁/2) + 2^(n₂/2).
Verify: compare with the hoped-for 2^((n₁+n₂)/2)
Why: The concatenation gives roughly max of the two individual securities plus a small factor, not their product. Concatenating a 128-bit and a 160-bit hash gives about 160-bit collision resistance, not 288. The intuition that two hashes must be much stronger than one is simply wrong for iterated constructions.
Figure (svg): Joux's multicollision: t successive two-way collisions in a Merkle-Damgard chain give two to the t colliding messages.
Anomaly
Concatenating SHA-1 and MD5 gives a 288-bit digest, and the obvious hope is 144-bit collision resistance.
Predict first
What does it actually give?
Correct: Roughly the security of the stronger one alone, because a multicollision on one is cheap and feeds the other
The practical consequence is that combining hashes is not a cheap way to buy security. If you need 256-bit collision resistance, use a 512-bit digest — do not concatenate two 256-bit ones.
It is also part of the case for SHA-3: a sponge does not admit the construction, because there is no chaining value an attacker can collide into.
Why: Joux's construction builds a huge multicollision on the first hash for a cost that is only linear in the number of messages produced, then searches inside that set for a collision under the second. The result is about max(n₁, n₂)/2 bits rather than (n₁+n₂)/2. The construction exploits nothing about either function except that both are iterated — so it is a weakness of the Merkle-Damgård shape, not of MD5 or SHA-1.
Figure (svg): Joux's multicollision: t successive two-way collisions in a Merkle-Damgard chain give two to the t colliding messages.
Section
Section 12.3 · pp. 251-253
Concept
Security proofs need to say something about the hash function, and nobody can prove anything about SHA-256 specifically. The random oracle model replaces it with an idealisation.
Random oracle — A function that, on each new input, returns a uniformly random output — and returns the same output whenever that input is repeated. Every party, including the attacker, may query it, and nobody can compute it without querying.
Under this assumption, many schemes can be proved secure: the proof shows that an attacker who breaks the scheme could be used to solve a hard problem, by watching which queries she makes to the oracle.
The book uses it in this chapter to relate the security of a simple cryptosystem to the non-invertibility of a one-way function, and it is part of the Provable Security thread begun in Section 4.4.
The honest caveat: SHA-256 is not a random oracle. It is a fixed, public, efficiently computable function, so an attacker can evaluate it without asking anyone. There exist artificial schemes that are provably secure in the model and insecure with any real hash. So a random oracle proof is strong evidence rather than a guarantee — and in practice, schemes proved this way have held up well.
Figure (svg): The random oracle as a black box returning fresh randomness for each new query and repeating itself for old ones.
Section
Section 12.4 · pp. 253-255
Concept
A hash takes arbitrary input to output that appears random, and two distinct inputs give very different outputs. That is a property it shares with a good cipher — so a hash can be made to encrypt.
The construction is a stream cipher, and the book compares it directly to OFB mode from Chapter 6. Alice and Bob share a key K_AB and an initialization vector.
\[ x_i = L_8\bigl(h(K_{AB} \, \| \, IV \, \| \, i)\bigr), \qquad c_i = p_i \oplus x_i \]
Take the leftmost byte of a hash of the key, the IV and a counter; XOR it with a plaintext byte. Increment the counter and repeat. That is a keystream generator built from a hash, and it is exactly how the HKDF and CTR-DRBG constructions work in practice.
And it inherits everything. Chapter 4's warnings apply in full: the counter must never repeat under one key, or two messages share keystream and the key cancels. It provides no integrity — flipping a ciphertext bit flips exactly the corresponding plaintext bit — so it must be paired with a MAC.
Figure (svg): Using a hash as a stream cipher: hash the key with a counter to make keystream, then XOR it with the plaintext.
Socratic
The keystream is h(K ‖ IV ‖ i). The counter i already ensures no block repeats within a message.
Discussion prompt
What does the IV add, and what happens without it?
Hint: Consider two different messages sent under the same key.
Answer:
Without an IV, every message under key K gets the same keystream, because it depends only on K and the position i. Two messages then XOR to the XOR of their plaintexts — Section 4.3's two-time pad, exactly.
The counter prevents repetition within a message; the IV prevents it between messages. They solve different halves of the same requirement, and both are needed.
The IV need not be secret — it travels with the ciphertext. It must be unique per message under a given key, which is Chapter 6's IV requirement restated.
And it must be long enough that random choice does not repeat: by this chapter's own birthday bound, a 64-bit random IV repeats after about 2³² messages, which a busy server reaches. Either use a counter, or make the IV wide enough that 2^(n/2) exceeds any plausible message count.
So this one construction pulls together three of the book's recurring requirements: never reuse keystream, make uniqueness structural, and size random values against the birthday bound.
Section
Section 12.5 · pp. 255-256
Concept
Two questions Bob needs answered about any message: is it really from Alice, and has it been changed? A message authentication code answers both. Alice sends the pair (m, MAC).
HMAC, invented in 1996 by Bellare, Canetti and Krawczyk, is the standard construction and is used in IPSec and TLS. Take a hash H processing 512-bit blocks and a shared key K, padded with zeros to 512 bits or hashed down if longer. Define two constants:
\[ \text{opad} = \texttt{5C5C\ldots5C}, \qquad \text{ipad} = \texttt{3636\ldots36} \]
\[ \text{HMAC}(m, K) = H\bigl((K \oplus \text{opad}) \, \| \, H((K \oplus \text{ipad}) \, \| \, m)\bigr) \]
The inner hash is the natural construction and is exactly what Section 11.3 showed falls to length extension. The outer hash fixes it: the value Eve sees is not the internal state of any computation she can continue.
Figure (svg): HMAC: an inner hash of the padded key with the message, then an outer hash of the padded key with that result.
Worked example
Follow what an attacker can and cannot do at each stage.
Against H(K ‖ m): Eve holds the tag, which is the state after processing K ‖ m
Why: She appends blocks and computes a valid tag for the extended message. No key needed.
Against HMAC: Eve holds H((K ⊕ opad) ‖ inner)
Why: This is the state after the outer hash. Extending it appends blocks to the outer computation, whose input is (K ⊕ opad) ‖ inner — and she cannot construct a matching message, because that input is not the message.
She would need to control the outer hash's input, which requires the inner hash's output, which requires K
Why: So the length extension route is closed structurally rather than by patching.
The two different pads matter: ipad and opad differ, so the two hashes effectively use two different keys
Why: If both used K unchanged, relations between the inner and outer computations would become available.
Verify: Bob verifies by recomputing HMAC(m, K) and comparing
Why: And the comparison must be constant-time, or the timing of a failed compare reveals how many bytes matched — an implementation requirement, not a design one, and one that has broken real systems.
Figure (svg): HMAC: an inner hash of the padded key with the message, then an outer hash of the padded key with that result.
Concept
Both produce a tag that proves a message is authentic. They differ in who is convinced, and the difference is Chapter 1's fourth objective.
A MAC uses a shared key. Bob is convinced the message came from Alice, because only Alice and Bob hold K and Bob knows he did not write it. But he cannot prove this to anyone else — a judge cannot rule out Bob having produced the tag himself.
A signature uses Alice's private key. Anyone with her public key can verify, and nobody else could have produced it. That gives non-repudiation, which no shared-key construction can provide.
The trade is cost: a MAC is a couple of hash computations, while a signature is a public-key operation — orders of magnitude slower, per Chapter 1. So protocols use signatures once, during a handshake, and MACs on every record afterwards. TLS does exactly this.
Figure (svg): A MAC convinces the recipient; a signature convinces everyone else.
Section
Section 12.6 · pp. 256-262
Concept
Alice authenticates to a verifier, Veronica — a terminal, a phone, an email service. They share the password, which is a long-term secret from a much smaller space than a cryptographic key, so it has small entropy.
Veronica keeps a list of users and passwords. The basic protocol is three messages:
Three problems, and each has a standard fix:
Figure (svg): The basic password protocol, with the three points at which it fails marked.
Worked example
Each fix answers one specific attack, and the order matters.
Store h(salt ‖ password) rather than the password
Why: A breach of the list no longer yields credentials. The salt forces the attacker to work per account rather than once — Chapter 7's calculation.
Use a slow, memory-hard hash — Argon2, scrypt, bcrypt
Why: Because passwords have small entropy, the only defence against enumeration is making each guess expensive. This is the fix that matters most.
Send the password only inside an authenticated encrypted channel
Why: Otherwise it is read in transit. Note the channel must be authenticated, or Chapter 10's intruder-in-the-middle simply terminates it.
Better: use a challenge-response so the password never travels at all
Why: Veronica sends a random nonce; Alice returns a function of the nonce and her password. An eavesdropper sees a value useless for a future login, which defeats replay.
Verify: check what a compromised Veronica now learns
Why: With challenge-response, Veronica must still be able to verify — so she holds something password-equivalent, and her compromise still enables offline guessing. Fixing that needs a password-authenticated key exchange such as SRP or OPAQUE, where the server stores a value that does not permit offline attack. Each fix reveals the next problem, which is why this is a protocol and not a formula.
Figure (svg): A MAC convinces the recipient; a signature convinces everyone else.
Section
Section 12.7 · pp. 262-264
Concept
A hash pointer is a pointer to where data is stored, combined with a cryptographic hash of the value being pointed at.
Its use is immediate: if anyone alters the data block, the hash in the pointer no longer matches — assuming nobody has altered the pointer. That proviso is the whole design problem, and it is what the chain solves.
A hash chain is iterated hashing: h(h(h(x))). It appears in one-time password schemes, where publishing the n-th iterate lets you later prove knowledge of the (n−1)-th, and nobody can run the chain forwards from what they have seen.
Chapter 11's Merkle-Damgård construction is itself a hash chain, and the length extension attack is the observation that a chain can always be extended by whoever holds its end.
Figure (svg): A blockchain: each block carries a hash pointer to the previous one, so altering any block invalidates every hash after it.
Concept
Take an ordered collection of data blocks and build a linked list — but replace each ordinary pointer with a hash pointer. Each block contains its data, the hash of the previous block, and a pointer to it. A final hash pointer references the end of the chain.
The consequence is tamper-evidence. Alter block 1 and its hash changes, so block 2's stored hash no longer matches. To hide that, an attacker must also alter block 2 — which changes its hash, breaking block 3. The alteration propagates to the end.
So holding just the final hash pointer is enough to detect any change anywhere in the entire history. That is the property, and it is achieved with nothing but a hash function.
What it does not provide is agreement. Tamper-evidence says a change is detectable by someone holding the true head. Deciding which head is the true one, among parties who do not trust each other, is a different problem — and it is what proof of work, and Chapter 16's cryptocurrencies, are for.
Figure (svg): A blockchain: each block carries a hash pointer to the previous one, so altering any block invalidates every hash after it.
Concept
A blockchain's blocks usually contain many transactions, and a Merkle tree commits to all of them with a single hash.
Hash the items in pairs, then hash those hashes in pairs, and so on up to a single root. The root goes into the block header, so the header commits to every transaction.
The payoff is a short membership proof. To prove that a particular transaction is in the tree, supply its sibling and one node per level — about log₂ n hashes, rather than the entire set. A verifier recomputes the path to the root and compares.
This is what lets a lightweight client verify that a payment is included in a block without downloading the block, and the same idea appears in certificate transparency logs and in most distributed storage systems.
Figure (svg): A Merkle tree: leaves hashed in pairs up to a single root, so any leaf can be proved with a logarithmic number of hashes.
Notation
One approximation, and it settles hash sizes, block sizes, nonce sizes and group sizes.
Annotate
On: \( P(\text{some collision}) \approx 1 - e^{-k^{2}/(2N)} \)
The 24-bit IV of WEP fails this test at a few thousand packets, and 64-bit block ciphers fail it at 32 GB. Both were shipped.
Definition probe
The choice turns on who has to be convinced, not on how strong the guarantee is.
Sort into buckets
Sort each requirement.
Elimination
Four ways of combining a key and a message with a hash.
Eliminate the wrong options
Which one is sound?
Survives elimination: c
Why: HMAC is the only one of the four with a security proof, and each of its features answers a specific failure: the outer hash closes length extension, and the two distinct pads make the inner and outer computations use effectively different keys. Note that (b) and (d) are both plausible-looking fixes that a careful person might invent, and neither is sound — which is the argument for using the standard construction rather than devising one.
Explain it to yourself
A blockchain makes tampering detectable by anyone holding the true head.
Discussion prompt
Explain why that is not the same as knowing which chain is the real one, and what has to be added.
Hint: Imagine two parties each holding a different head, both internally consistent.
Answer:
Tamper-evidence is relative to a head. Given the correct final hash, any alteration anywhere in the history is detectable. But an attacker can build an entirely different chain, internally consistent from block 0, with its own final hash — and nothing in the hash function says which of the two is real.
So the primitive gives integrity, not agreement. All parties must independently arrive at the same head, and hashing alone cannot make them.
What has to be added is a cost. Proof of work requires each block's hash to fall below a target, so extending a chain is expensive. The honest chain accumulates work faster than any single attacker, so 'the chain with the most work' becomes a rule everyone can apply and nobody can cheaply subvert.
Note that this is an economic argument, not a cryptographic one. It rests on the attacker controlling less than half the computing power, which is an assumption about the world rather than about mathematics — and it is the part of Chapter 16 that is genuinely new.
The general lesson: cryptography can make something detectable; making a distributed set of parties agree is a different problem, and the hash function is only its first ingredient.
Comparison
This chapter has used the same hash function four ways. Fill the blanks.
Comparison matrix
| Use | Property relied on | What breaks without it |
|---|---|---|
| Signing a document's digest | collision resistance | the birthday attack forges a signature on an unseen document |
| HMAC | the construction, not just the hash | length extension forges tags without the key |
| Password storage | preimage resistance and slowness | a dictionary attack recovers every password |
| A blockchain's hash pointers | collision resistance | an attacker substitutes a colliding block undetected |
One primitive, four properties relied on, and four completely different failures. 'Is the hash secure?' is never the right question.
Ranking
Each is a birthday-bound attack from somewhere in this course.
Put in order
Why: 2¹² ≈ 4000 packets for WEP; 2³² blocks ≈ 32 GB for Sweet32; about 2⁶³ hash computations for the 2017 SHA-1 collision, below its nominal 2⁸⁰; and 2¹²⁸ for SHA-256, which is beyond any adversary. Four instances of one formula, spanning twenty-six orders of magnitude — and the first two were shipped in standards by people who had not done the arithmetic.
Figure (svg): The probability of a shared birthday rising steeply with the number of people, crossing one half at twenty-three.
Error analysis
From a mobile app's backend specification.
Annotate
Four decisions and four documented attacks, and not one of them requires breaking a hash function.
Edge cases
Chapter 6's modes require a non-repeating nonce, and this chapter supplies the arithmetic.
Discussion prompt
For a random nonce, how many bits are needed, and when should you use a counter instead?
Hint: Compare 2^(n/2) with the number of messages the system will send.
Answer:
A random n-bit nonce repeats after about 2^(n/2) messages. So 96 bits — GCM's standard size — repeats after about 2⁴⁸, which is 280 trillion messages. Safe for essentially any system.
64 bits repeats after 2³², about four billion messages, which a busy service reaches in weeks. That is not enough.
24 bits repeats after 2¹² — four thousand — which is WEP, and it is why WEP fell within hours of a busy network's operation.
A counter is strictly better where it is available: it cannot repeat until it wraps, so a 64-bit counter gives 2⁶⁴ messages rather than 2³². The birthday bound applies only to random choice.
Use a counter when you control persistent state, and randomness when you do not — for example across independent senders sharing a key, where a counter would need coordination. And where randomness is unavoidable, size it against the square root.
The failure mode to watch: a counter that resets. A VM snapshot restore, a database rollback or a failover to a standby that starts from zero all reintroduce repetition, which is why random nonces are sometimes chosen despite the worse bound.
Commit first
A distributed ledger uses SHA-256 hash pointers, Merkle trees, and proof of work.
Predict first
What is the most likely cause of a real failure?
Correct: Consensus failure — an attacker with enough computing power to outpace the honest chain, or a bug in the agreement rules
Smaller proof-of-work chains have been reorganised by rented hashpower repeatedly; the assumption that no one party controls half the network is empirical and sometimes false.
This is the chapter's closing point in a different form: the primitive is not where systems break. Chapter 16 takes the argument up in full.
Why: The cryptography here is the strongest part. SHA-256 collisions cost 2¹²⁸, and the hash pointer construction is sound. What actually fails is the agreement layer — majority-hashpower attacks on small chains, chain reorganisations, and implementation bugs in the consensus rules — because that layer rests on an economic assumption about who controls what, not on a mathematical one.
Faded example
Four blanks, and the whole derivation is on the page.
Fill in the blanks
Among k items there are about k²/2 pairs. Each pair collides with probability 1/N when there are N possible values. Setting the expected number of collisions to 1 gives k ≈ √N. For an n-bit hash, N = 2ⁿ, so a collision costs about 2^(n/2).
Why: The whole derivation is the first blank: the number of opportunities is quadratic in the sample size while the effort is linear, so the square root falls out. Everything else is substitution. It is worth being able to reproduce, because the same three lines apply to block sizes, nonce sizes, IV sizes and group orders — four separate design decisions settled by one calculation.
Explain it
Someone insists that 23 people cannot possibly give a 50% chance, since there are 365 days.
Discussion prompt
Give the explanation that actually persuades, and name the specific mistake they are making.
Hint: They are answering a different question from the one asked.
Answer:
Name the mistake first: they are computing the chance that someone shares their birthday, which is indeed about 23/365 ≈ 6%. The question asks whether any two of the 23 share one, which is a different and much larger event.
Then count the pairs. 23 people make 253 pairs, and each pair has a 1/365 chance. 253/365 is about 0.69, so an expected count near one match — which lands the probability around a half.
Then give the incremental picture, which is the book's: line the people up. The second person must avoid 1 day, the third 2, the tenth 9, the twenty-third 22. Multiplying twenty-two such factors erodes the probability faster than intuition suggests.
Then the sanity check they can run: ask how many people are needed for a 50% chance that someone shares your birthday. The answer is 253, and the contrast between 23 and 253 is what makes the distinction concrete.
And the reason it matters here: every collision-based attack in cryptography is the 23 case, not the 253 case, and designers who size a field by the wrong one ship WEP.
Constraint
Fifty thousand devices report telemetry to a server. Each has a unique key provisioned at manufacture. Messages are 40 bytes and sent every ten seconds, for a ten-year life.
Discussion prompt
Specify the message authentication, and check every number against this chapter's bounds.
Hint: Count how many messages each key will ever protect, then size the nonce.
Answer:
Count first: ten years at one message per ten seconds is about 3 × 10⁷ messages per device — under 2²⁵. That number drives everything else.
HMAC-SHA256, truncated to 128 bits. A full 256-bit tag on a 40-byte message is absurd overhead; 128 bits gives a forgery probability of 2⁻¹²⁸ per attempt, which is ample. Truncating a MAC is safe in a way that truncating a hash for collision resistance is not.
A per-device counter as the nonce, not randomness. With 2²⁵ messages a random 64-bit nonce would be fine by the birthday bound, but a counter is free here because the device has persistent state, and it also gives replay protection.
Reject any message whose counter is not greater than the last seen. This is what turns the nonce into a replay defence, and it costs one stored integer per device.
Per-device keys, already specified — and worth noting why: with a shared key, one extracted device compromises the fleet, and IoT devices are physically accessible by definition.
And a re-provisioning path, because ten years is long enough that the key or the algorithm will need to change. Chapter 7's DES lesson, once more.
Missing information
A design document states that all inter-service messages are authenticated.
Discussion prompt
List what a reviewer still cannot determine, ordered by risk.
Hint: Authentication has several parts, and replay is the one usually forgotten.
Answer:
Is it a MAC or a signature — and does anyone need non-repudiation? If a third party must ever adjudicate, a MAC is the wrong tool and no amount of key management fixes it.
Is replay prevented? A valid message captured and re-sent is still valid unless a nonce, counter or timestamp window says otherwise. This is the omission most often missed, because the tag verifies perfectly.
What construction? H(K ‖ m) is not a MAC. If the answer is anything other than HMAC or a standard AEAD, ask why.
Is the comparison constant-time? A byte-by-byte compare leaks the tag through timing.
Are keys per-peer? A shared key across services means one compromise forges for all of them.
Is the tag long enough? A 32-bit tag gives a forgery one attempt in four billion, which an attacker who can retry will reach.
Six questions, and 'authenticated' answers none of them. The pattern across this course is now unmistakable: naming the goal is not specifying the mechanism.
Picture it
The probability of a shared birthday against the number of people. The steepness between 10 and 30 is the whole phenomenon.
Figure (svg): The probability of a shared birthday rising steeply with the number of people, crossing one half at twenty-three.
It is not that any particular pair is likely to match — each pair has a 1-in-365 chance. It is that there are so many pairs, and the count grows quadratically while the room fills linearly.
Hypothesis
A system uses HMAC-SHA256 with a 256-bit random key, correctly constructed.
Predict first
Where is the realistic attack?
Correct: Replay of a previously valid message, or a non-constant-time tag comparison
Replay is the omission people forget, because the tag verifies perfectly — nothing is wrong with the message except that it already happened. A counter, a nonce or a timestamp window is required, and it is a separate design decision from the MAC.
Timing is the implementation trap. if (tag != expected) reject compiled naively compares byte by byte and stops at the first difference, so the time taken reveals the length of the matching prefix. Every crypto library provides a constant-time compare for exactly this.
Why: HMAC-SHA256 with a strong key has no known cryptanalytic attack, and guessing a 256-bit tag is hopeless. What breaks in practice is everything around it: a captured message replayed later still verifies, because a MAC says nothing about freshness; and a byte-by-byte comparison that returns early lets an attacker recover a valid tag one byte at a time by measuring response times.
Discrimination
Three properties that are routinely conflated, and each needs a different mechanism.
Sort into buckets
Sort each mechanism by the property it provides.
Trade off
A short message with a long tag is mostly overhead. Fill the blanks and the sizing becomes a calculation rather than a habit.
Comparison matrix
| Tag length | Forgery chance per attempt | Appropriate when |
|---|---|---|
| 32 bits | 1 in 4 billion | the verifier rate-limits attempts and the message is worthless |
| 64 bits | 1 in 1.8 × 10¹⁹ | constrained links where the verifier limits retries |
| 128 bits | 1 in 3.4 × 10³⁸ | the general default |
| 256 bits | negligible | rarely needed; full HMAC-SHA256 output |
Note the asymmetry with hashing: truncating a MAC is safe because the attacker must guess a value she cannot compute, while truncating a hash halves collision resistance immediately. The two look alike and size completely differently.
Socratic
A salt is a public, non-secret random value stored beside the hash. It hides nothing.
Discussion prompt
So why does adding it change the attacker's cost by orders of magnitude?
Hint: Count the attacker's work with and without one, for a file of many accounts.
Answer:
Without a salt, the attacker's work is independent of the number of accounts. Hash a ten-million-word dictionary once, then compare against every stored digest by lookup. Ten million hashes break the whole file.
With a distinct salt per account, the work multiplies by the number of accounts. Each word must be re-hashed against each salt: ten million words against ten thousand accounts is 10¹¹ hashes.
And it kills precomputation entirely. A rainbow table's value is being built once and reused across targets; a salt makes each target need its own table, so building one is never worth it.
Which is why the salt need not be secret. Its job is not to hide anything — it is to make the attacker's work scale with the number of victims instead of being amortised across them.
The same idea has appeared three times now: the IV in CBC, the nonce in CTR, and the salt here. All three are public, all three must be unique, and all three exist to stop a deterministic function producing the same output twice. It is one idea with three names.
Matching
Five constructions from this chapter and the last, each answering something specific.
Match the pairs
Why: Five constructions, five failures, and not one of them is a weakness in the hash function. Two are structural (the outer hash, the tree), two are about making a deterministic function non-repeating (the salt, the sequence number), and one is about the implementation rather than the design. That distribution is a fair summary of where real systems break.
Error analysis
From a web application's design notes.
Annotate
The fix is one line: generate the token from a cryptographic random source, store only its hash, and expire it. Nothing needs to be derived from anything.
Scale up
One formula against four real designs. Track how many values are drawn before a repeat is likely.
Step through it
Which of the four was sized by someone who did the calculation?
Only the last. The first two were sized by what fitted the existing format, and both became named attacks — which is the argument for doing this arithmetic at design time rather than discovering it in a paper.
Real world
The construction predates blockchains by thirty years and is used far more widely than for them.
Discussion prompt
Name three systems that use Merkle trees and say what each gains from the logarithmic membership proof.
Hint: Version control, certificate monitoring, and file synchronisation.
Answer:
Certificate Transparency. Every certificate issued by a participating CA is appended to a public log structured as a Merkle tree. A browser can verify that a certificate is in the log with a proof of about 30 hashes, rather than downloading billions of entries — and the tree's append-only structure makes retroactive removal detectable.
Git. A tree object hashes its entries, and a commit hashes its tree — so a commit hash commits to the entire working tree. Comparing two large directories reduces to comparing two root hashes, and finding what differs walks down only the differing branches.
File synchronisation and backup. rsync-style tools and content-addressed stores compare trees of hashes to find which blocks differ, transferring only those. Comparing two 4 TB volumes costs a few hundred hashes rather than 8 TB of reading.
The common gain is the same in all three: a single root value commits to an arbitrarily large collection, and any question about one member costs log n rather than n. That is what makes verification affordable for a party who cannot hold the whole dataset.
It is also why the construction is worth knowing independently of any application — it is the standard answer to 'commit to a large set, prove one element'.
Commit first
A system uses SHA-256 for password storage with a per-user salt, HMAC-SHA256 for API authentication, and SHA-256 hash pointers in an audit log.
Predict first
Which component is most likely to be exploited?
Correct: The password storage — SHA-256 is fast, so guessing is cheap even with a salt
The fix is Argon2id, scrypt or bcrypt with a tuned work factor — and a rehash-on-login path so the factor can rise as hardware improves.
Note that all three uses in the question employ the same primitive correctly by the standards of Chapter 11, and one of them is still wrong. The right question is never whether the hash is secure, but whether its speed is on your side or the attacker's.
Why: The salt is present and correct, so precomputation is dead and the attacker must work per account. But SHA-256 is deliberately fast, and a GPU computes billions per second — so a stolen database still yields every weak password in hours. Salting fixes amortisation across accounts; it does nothing about throughput, and only a slow, memory-hard function does.
Pattern
The birthday bound is the most reusable thing in this chapter, and it settles four separate questions that look unrelated.
The habit worth building: whenever a design draws values from a space and requires no repeats, compute the square root of the space size and compare it with how many will be drawn. WEP, triple DES and MD5 signatures all failed that comparison, and all three were standards.
Figure (svg): The probability of a shared birthday rising steeply with the number of people, crossing one half at twenty-three.
Trap
The trap. MD5 produces a 128-bit digest, so breaking it requires 2¹²⁸ work — the same as AES-128, which is beyond any adversary. So MD5 is adequate for signing, and the objections are theoretical.
This reasoning was widely held into the 2000s, and it is wrong twice over.
First error: the birthday bound. Collision resistance is 2^(n/2), not 2ⁿ. MD5's 128-bit digest gives 64-bit collision resistance generically — about 1.8 × 10¹⁹, reachable by a determined attacker even without cryptanalysis. A signature hash must be twice the security level wanted.
Second error: cryptanalysis makes it worse, never better. The generic bound is an upper limit on the defender's guarantee, not a lower limit on the attacker's cost. MD5 collisions now take seconds, five orders of magnitude below even its 2⁶⁴ nominal figure.
And the comparison with AES-128 is a category error. AES's security parameter is the key length, and the attack is exhaustive search at 2¹²⁸. A hash's collision security is half its digest length, and the attack is a birthday search. Equal-looking numbers, different meanings.
The rule: for a hash, always ask which property, then apply the right exponent — n for preimages, n/2 for collisions. Quoting the digest length as the security level is the commonest error about hash functions, and it is what kept MD5 in certificates until 2008.
Check
Work it out before you click.
Check your understanding
You need 112-bit collision resistance for a signature scheme. What digest length is required?
Answer: B
Why: Collision resistance is 2^(n/2), so n must be twice the security level: 224 bits. This is exactly why SHA-224 exists — it pairs with 112-bit security, which is the level triple DES was quoted at. The doubling is the whole content of the birthday bound.
Check
Consider what an attacker holding one valid tag can do.
Check your understanding
Which of these can an attacker extend without knowing the key?
Answer: B
Why: SHA-256 uses Merkle-Damgård, so the tag is the internal state and an attacker resumes the computation from it, appending blocks and producing a valid tag. This is the length extension attack, and it is why HMAC exists.
Check
Separate what the hash function does from what it does not.
Check your understanding
A blockchain's hash pointers guarantee what, exactly?
Answer: B
Why: Altering any block changes its hash, which breaks the next block's stored pointer, and so on to the end — so one correct final hash detects any change anywhere. That is tamper-evidence, and it is all the hash function provides.
Connect it up
One formula and five applications, and they connect tightly.
Draw it
Derive the birthday bound in three lines and list the four design decisions it settles, with a number for each. Then draw the multicollision construction and state what it does to concatenated hashes. Write HMAC's formula and say what each of the two hashes prevents. Finally sketch a blockchain's hash pointers, state precisely what they guarantee, and state what they do not — and name what has to be added to get it.
The last line is the one that separates a cryptographic guarantee from a systems one, and Chapter 16 is entirely about the gap.
Exit ticket
One question about the number that runs through the whole chapter.
Predict first
Why does an n-bit hash give only n/2 bits of collision resistance?
Correct: Because the number of pairs among k samples grows as k², so a collision becomes likely once k reaches √(2ⁿ)
Why: The attacker is not aiming at a target; she is looking for any agreement among her samples, and k samples give about k²/2 chances. Setting that equal to the space size gives k ≈ 2^(n/2). Nothing is wrong with the hash — the bound is generic, applies to a perfect function, and cannot be improved by any design. It is a fact about counting pairs, and the same counting sets block sizes, nonce sizes and group orders.
Recap
One counting argument, and the applications that make hash functions the most-used primitive in the book.
Chapter 13 next. Digital signatures proper: RSA signatures, the ElGamal signature scheme, why hashing before signing is mandatory rather than an optimisation, and the birthday attack applied to signatures once more.
Figure (svg): A MAC convinces the recipient; a signature convinces everyone else.
Want this taught 1-on-1? Alexander tutors Cryptography — $55/session, free consultation.