Skip to content
Part IA Lent Term

Universal Hashing

The Problem with Fixed Hash Functions

Any fixed hash function hh can be adversarially exploited. If an attacker knows (or reverse-engineers) the hash function, they can craft a set of keys that all map to the same slot:

h(k1)=h(k2)==h(kn)=sh(k_1) = h(k_2) = \cdots = h(k_n) = s

The result: chaining degrades to a linked list of length nn, or open addressing probes through all slots. All operations become Θ(n)\Theta(n). This is not just a theoretical concern: it has been used in denial-of-service attacks against web frameworks and network infrastructure.

Randomising the input data or picking a random pivot (as in quicksort) reduces the probability of hitting the worst case, but for hash tables a stronger guarantee exists.

Universal Families of Hash Functions

Universal hashing: the hash function is chosen randomly at runtime from a family H\mathcal{H} of hash functions. The family is designed so that, regardless of which keys the adversary provides, the probability of collision between any two distinct keys is bounded.

Definition: A family H\mathcal{H} of functions mapping UU to {0,1,,m1}\{0, 1, \ldots, m-1\} is universal if, for any distinct k1,k2Uk_1, k_2 \in U:

PrhH[h(k1)=h(k2)]1m\Pr_{h \in \mathcal{H}}[h(k_1) = h(k_2)] \le \frac{1}{m}

The probability is taken over the random choice of hh from H\mathcal{H}, not over the choice of keys. The keys can be chosen adversarially after H\mathcal{H} is known; the guarantee still holds.

A Concrete Universal Family

Choose a prime p>Up > |U| (larger than any possible key value). Define:

ha,b(k)=((ak+b)modp)modmh_{a,b}(k) = ((ak + b) \bmod p) \bmod m

where a{1,2,,p1}a \in \{1, 2, \ldots, p-1\} and b{0,1,,p1}b \in \{0, 1, \ldots, p-1\} are chosen uniformly at random. The family Hp,m={ha,b}\mathcal{H}_{p,m} = \{h_{a,b}\} is universal.

Proof sketch: For any k1k2k_1 \neq k_2, the values (ak1+b)modp(ak_1 + b) \bmod p and (ak2+b)modp(ak_2 + b) \bmod p are uniformly distributed and pairwise independent over {0,,p1}\{0, \ldots, p-1\}. The probability they collide modulo mm is at most 1/m1/m.

Why Universal Hashing Works

With a universal family and chaining, the expected search time is O(1+α)O(1 + \alpha) even against an adversary. The adversary can choose keys knowing the family H\mathcal{H} but not which hHh \in \mathcal{H} will be chosen at runtime.

The proof: for any search key kk, the expected number of other keys in the same chain is:

E[collisions]=kkPr[h(k)=h(k)](n1)1m<α\mathbb{E}[\text{collisions}] = \sum_{k' \neq k} \Pr[h(k) = h(k')] \le (n-1) \cdot \frac{1}{m} < \alpha

Thus the expected chain length is <1+α< 1 + \alpha, giving O(1)O(1) expected search when α=O(1)\alpha = O(1).

Static Dictionaries and Perfect Hashing

For a static dictionary (keys known in advance, no insert/delete after construction), universal hashing can achieve O(1)O(1) worst-case search time with no collisions, using a two-level scheme:

  1. Hash nn keys into nn primary slots using a universal function.
  2. For each slot with nin_i keys, build a secondary hash table of size ni2n_i^2 using another universal function.

The expected total space is O(n)O(n), and with high probability (by choosing random hash functions repeatedly until no collisions occur), all secondary tables are collision-free. This is called perfect hashing.

Practical Considerations

Many production hash table implementations (Python’s dict, Rust’s HashMap) use a fixed high-quality hash function with per-process randomisation (a random seed). This approximates universal hashing: the seed is chosen at startup, making it difficult for an attacker to predict slot assignments.

The Cambridge course treats universal hashing as the theoretical foundation: a fixed function cannot beat an adversary, but a randomly chosen function from a universal family can.

Summary

ConceptDefinition
Fixed hash functionVulnerable to adversarial input
Universal family H\mathcal{H}Pr[h(k1)=h(k2)]1/m\Pr[h(k_1)=h(k_2)] \le 1/m for any k1k2k_1 \neq k_2
Example familyha,b(k)=((ak+b)modp)modmh_{a,b}(k) = ((ak+b) \bmod p) \bmod m
Expected search timeO(1+α)O(1 + \alpha) even against adversary
Perfect hashingZero collisions, O(1)O(1) worst-case search, O(n)O(n) expected space
Per-process randomisationPractical approximation of universal hashing