How a PUF works, from silicon variation to a login protocol
Physical unclonable functions turn manufacturing randomness into a fingerprint no one can copy. Here is how they are built, measured, made reliable and attacked, with simulations you can run.
, 8 min read
Every connected device has to answer one question before anything else: are you really who you say you are? The usual answer is a secret key stored in flash or fuses. That works until someone opens the package. Stored keys can be read with a probe station, a laser, a power trace or a firmware bug, and once a key is copied, a cheap clone is indistinguishable from the real device.
A physical unclonable function (PUF) removes the stored key. Instead of remembering a secret, the chip re-measures one from its own physical structure every time it needs it. Nobody, not even the manufacturer, can choose that secret or build a second chip with the same one.
This post walks through how that works, from the transistor level to a complete authentication protocol, and ends with the attacks that make PUF design hard.
The idea in one sentence
A PUF is a circuit that maps a challenge to a response , where the mapping depends on tiny, uncontrollable manufacturing differences:
Two chips built from the same layout file implement two different functions and . A pair is called a challenge–response pair (CRP).
PUFs come in two families:
| Family | Challenges | Typical use | Examples |
|---|---|---|---|
| Weak PUF | Few or one | Generate one device key on chip | SRAM PUF, butterfly PUF |
| Strong PUF | Exponentially many | Challenge–response authentication | Arbiter PUF, XOR arbiter PUF |
Where the randomness comes from
No two transistors are identical. During fabrication, the number and position of dopant atoms in a channel, the roughness of etched line edges and the thickness of the gate oxide all vary at the atomic scale. The result is that every transistor has a slightly different threshold voltage and every wire a slightly different delay.
Chip designers normally fight this variation. A PUF designer amplifies it, by building circuits where two nominally identical parts compete and the winner is decided only by variation.
Design 1: the arbiter PUF
The arbiter PUF is the classic strong PUF. A single rising edge is sent down two paths through a chain of switch stages. Each stage either passes the two signals straight through or swaps them, depending on one challenge bit. At the end, an arbiter (a latch) records which signal arrived first.
Scroll sideways to see the whole diagram.
Because the delay differences add up stage by stage, the arbiter PUF has a neat mathematical description called the additive delay model. The final delay difference is a weighted sum:
The weight vector holds the chip’s physical delay differences. It is different on every chip and never leaves the silicon. The feature vector is a fixed transformation of the challenge, the same for every chip. Keep this linear form in mind; it comes back when we discuss attacks.
Design 2: memory-based PUFs
Some PUFs need no special circuit at all. An SRAM cell is two cross-coupled inverters. When power is applied, both start at zero and race; the stronger inverter wins and the cell settles to 0 or 1. Most cells have a strong preference set by transistor mismatch, so the power-up pattern of a memory block is a fingerprint.
Scroll sideways to see the whole diagram.
SRAM PUFs are popular because almost every microcontroller already has SRAM, so a fingerprint can be read in firmware before the memory is initialised. Their limitation is that they are weak PUFs: one block gives one fingerprint, so they are used to derive a key, not to answer millions of challenges.
Other common designs:
| Design | What competes | Strengths | Watch out for |
|---|---|---|---|
| Arbiter PUF | Two delay paths | Huge challenge space, tiny area | Easy to model with machine learning |
| XOR arbiter PUF | k arbiter chains, outputs XOR-ed | Much harder to model | Noise grows with k |
| Ring-oscillator PUF | Frequencies of two ring oscillators | Simple on FPGAs | Temperature drift, more power |
| SRAM PUF | Two inverters in each cell | No extra hardware | Ageing, needs power cycle |
| Butterfly PUF | Cross-coupled latches | SRAM-like on FPGAs | Layout must be symmetric |
How good is a PUF? Four numbers
A PUF is only useful if it is different across chips and stable within a chip. Both are measured with the fractional Hamming distance : the share of response bits that differ.
Uniqueness averages the distance between every pair of chips answering the same challenges. Ideal: 50%, so every bit is a coin flip between chips.
Reliability measures how much a chip disagrees with its own reference response over repeated reads , at different temperatures and voltages. Ideal: 100%.
Uniformity is the share of ones in a response; ideal 50%, otherwise an attacker can guess. Bit-aliasing checks that a given bit position is not biased the same way on every chip.
The best picture of a PUF’s quality is the two Hamming-distance distributions side by side. Below is a simulation of 40 chips with 64-stage arbiter PUFs (the script is in this site’s repository, tools/puf-sim.mjs). Hover over the bars to see exact values.
Show the numbers
| Metric | Simulated | Ideal |
|---|---|---|
| Uniqueness (mean inter-chip HD) | 50.0% | 50% |
| Reliability (1 − mean intra-chip HD) | 97.4% | 100% |
| Uniformity (share of 1-bits) | 49.7% | 50% |
| Worst intra-chip HD | 8.6% | as low as possible |
| Closest inter-chip HD | 31.3% | as high as possible |
The gap between the two humps is what makes authentication possible. A verifier picks a threshold inside the gap: a distance below means “same chip, a little noise”; above it means “a different chip”.
Using a PUF to log in
The simplest protocol has two phases. Enrolment happens once, in a trusted place such as the factory: the verifier applies many random challenges and stores the responses. Authentication happens in the field, every time the device connects.
Scroll sideways to see the whole diagram.
Two rules make this safe. First, the verifier never reuses a challenge, so a recorded CRP is useless to an eavesdropper. Second, the comparison uses a threshold instead of exact equality, because PUF responses are noisy.
In a large deployment, such as thousands of vehicles roaming between roadside units, one central verifier becomes a bottleneck and a single point of failure. In my research we anchor the enrolled data on a blockchain ledger instead, storing only hashes of expected responses, so any edge verifier can check a device without a central database (read the paper).
Scroll sideways to see the whole diagram.
Turning a noisy response into a key
Authentication tolerates a few flipped bits, but cryptography does not: a key that differs by one bit is a different key. Weak PUFs therefore use a fuzzy extractor, built from an error-correcting code.
Scroll sideways to see the whole diagram.
At enrolment, the Gen procedure picks a random codeword, XORs it with the response and publishes the result as helper data . Later, Rep XORs the noisy response with , which gives the codeword plus the few bit errors, decodes it to remove those errors, and recovers the exact key. Practical designs add a few tricks before the code:
- Majority voting: read the PUF several times and keep the most common value of each bit.
- Dark-bit masking: at enrolment, find the unstable bits and simply never use them.
- Concatenated codes: a repetition code inside a BCH or Reed–Muller code handles high error rates with less helper data.
How PUFs get attacked
Modelling attacks are the biggest threat to strong PUFs. Remember the additive delay model: the response is the sign of a linear function of . That means an attacker who eavesdrops on enough CRPs can train a linear classifier, such as logistic regression, and predict the PUF’s answer to any new challenge. The chip is then cloned in software.
The chart below shows that attack in simulation. A plain 64-stage arbiter PUF falls after a few hundred CRPs. XOR-ing four independent chains makes the function non-linear in , and the same attack stays at the level of a coin flip.
Show the numbers
| CRPs collected | Arbiter PUF | 4-XOR arbiter PUF |
|---|---|---|
| 50 | 69.7% | 49.7% |
| 100 | 77.4% | 50.3% |
| 200 | 87.5% | 50.2% |
| 500 | 93.3% | 51.7% |
| 1,000 | 96.3% | 47.9% |
| 2,000 | 98.5% | 49.7% |
| 5,000 | 98.8% | 49.1% |
| 10,000 | 99.4% | 48.7% |
XOR is not the end of the story: with enough CRPs, specialised logistic-regression variants and neural networks do break XOR arbiter PUFs with more chains, and noise and power side channels leak information too. Defences therefore combine several layers:
- Never expose raw CRPs. Hash or encrypt responses inside the device, and limit how many challenges can be asked.
- Use non-linear designs such as XOR, feed-forward or interpose PUFs, sized against current attacks.
- Bind the PUF to a protocol that uses each CRP once and refreshes enrolment data securely.
- Measure, don’t assume. Evaluate uniqueness, reliability and attack resistance on real hardware across temperature and voltage. We built PUFAnalytics, a Python library, for exactly this kind of evaluation.
Try it yourself
This self-contained script builds two simulated arbiter PUFs, measures their Hamming distances and then clones one with logistic regression. It needs only NumPy.
import numpy as np
rng = np.random.default_rng(seed=1)
N_STAGES = 64
def features(challenges):
"""Map 0/1 challenges (rows) to the parity feature vector Φ of the additive delay model."""
signs = 1 - 2 * challenges # 0 -> +1, 1 -> -1
phi = np.cumprod(signs[:, ::-1], axis=1)[:, ::-1] # Φ_i = Π_{j>=i} (1 - 2c_j)
return np.hstack([phi, np.ones((len(challenges), 1))]) # + bias term
class ArbiterPUF:
def __init__(self, n=N_STAGES, noise=0.05, rng=rng):
self.w = rng.normal(size=n + 1) # stage delay differences, fixed at manufacture
self.noise, self.rng = noise, rng
def respond(self, challenges, noisy=True):
delta = features(challenges) @ self.w
if noisy:
delta += self.rng.normal(scale=self.noise * np.linalg.norm(self.w), size=len(delta))
return (delta > 0).astype(int)
def hamming(a, b):
return np.mean(a != b)
chip_a, chip_b = ArbiterPUF(), ArbiterPUF()
C = rng.integers(0, 2, size=(128, N_STAGES))
print(f"same chip, two reads : {hamming(chip_a.respond(C), chip_a.respond(C)):.3f}")
print(f"chip A vs chip B : {hamming(chip_a.respond(C), chip_b.respond(C)):.3f}")
# --- Modelling attack: learn w from eavesdropped CRPs with logistic regression ---
def train_logreg(X, y, epochs=300, lr=0.5):
w = np.zeros(X.shape[1])
for _ in range(epochs):
p = 1 / (1 + np.exp(-X @ w))
w -= lr * X.T @ (p - y) / len(y)
return w
C_train = rng.integers(0, 2, size=(2000, N_STAGES))
C_test = rng.integers(0, 2, size=(5000, N_STAGES))
w_hat = train_logreg(features(C_train), chip_a.respond(C_train, noisy=False))
pred = (features(C_test) @ w_hat > 0).astype(int)
print(f"clone accuracy : {np.mean(pred == chip_a.respond(C_test, noisy=False)):.3f}")A run on my machine prints:
same chip, two reads : 0.031
chip A vs chip B : 0.531
clone accuracy : 0.974
Try changing noise, or replace ArbiterPUF with an XOR of four instances and watch the clone accuracy fall to about 50%.
Summary
- A PUF derives a secret from manufacturing variation, so there is no stored key to steal.
- Strong PUFs answer many challenges and suit authentication; weak PUFs derive one key.
- Quality is judged by uniqueness (about 50%), reliability (close to 100%) and uniformity (about 50%).
- Noise is handled by thresholds for authentication and fuzzy extractors for keys.
- Linear designs such as the plain arbiter PUF can be cloned with machine learning, so real systems need non-linear designs and protocols that never reveal raw CRPs.
Further reading
- B. Gassend, D. Clarke, M. van Dijk and S. Devadas, “Silicon physical random functions,” ACM CCS, 2002.
- G. E. Suh and S. Devadas, “Physical unclonable functions for device authentication and secret key generation,” DAC, 2007.
- J. Guajardo, S. Kumar, G.-J. Schrijen and P. Tuyls, “FPGA intrinsic PUFs and their use for IP protection,” CHES, 2007.
- Y. Dodis, L. Reyzin and A. Smith, “Fuzzy extractors: how to generate strong keys from biometrics and other noisy data,” EUROCRYPT, 2004.
- U. Rührmair, F. Sehnke, J. Sölter, G. Dror, S. Devadas and J. Schmidhuber, “Modeling attacks on physical unclonable functions,” ACM CCS, 2010.