The birthday problem, and why 64-bit hashes collide sooner than you think
Why 23 people are enough for a shared birthday, and why a 64-bit hash already collides after about 5 billion items.
Contents
Put people in a room. How large must be before two of them probably share a birthday? The answer, 23, surprises people because they compare to 365. The right comparison is the number of pairs, , and that grows quadratically.
The exact probability #
Assume equally likely days.1 Real birthdays are not uniform. Unevenness only makes collisions more likely, so 23 people is enough in real rooms too. Seat people one at a time; the -th person avoids everyone before them with probability . So
Using the inequality , a consequence of convexity,2 The function is convex, and is its tangent line at , so the line lies below the curve. on each factor of (1) and summing the exponents gives a clean upper bound:
When a collision becomes likely #
Theorem 1 (Square-root law). With equally likely values and , two of the values coincide with probability at least . In particular suffices.
Proof. By (2), . ∎
For the condition reads , and is the first value that meets it, since .
Try it #
Drag the slider to 23 and notice that the curve crosses one half there, then drag it to 57: the probability is already above 99%.
Why this matters for hashing #
Replace “birthdays” with “hash values”. A -bit hash has outputs, so by Theorem 1 a collision is more likely than not after about items. A 64-bit hash, which sounds enormous, gets there after roughly billion items. That is a normal day for a large database.
import math
def items_until_likely_collision(bits: int) -> float:
"""Smallest n (as a real number) with n^2 >= 2 * 2**bits * ln 2."""
return math.sqrt(2 * 2**bits * math.log(2))
print(f"{items_until_likely_collision(64):.3e}") # 5.057e+09
The same square root explains why birthday attacks halve the security of a hash function, and why 128-bit identifiers are the usual choice when collisions must essentially never happen.