The one-sentence version
How do you confirm that "the person talking to me is the same person I talked to last time"? The simplest method is called TOFU (Trust On First Use): record the other party's public key during the first encounter, and compare it with the recorded one every time thereafter; if it changes, sound the alarm.
It cannot prevent being "tricked on the first encounter," but it compresses the attack window to that single moment. SSH's known_hosts, Signal's safety numbers, and mobile app certificate pinning all follow this logic; a more advanced "key transparency" attempts to protect even that first encounter.
This article has three layers:
- Layer 1: The Intuition: Remembering what someone looks like
- Layer 2: Real-World Use: SSH, Signal, App certificate pinning, and the lessons from HPKP's failure
- Layer 3: Principles and engineering key points: What to pin, where to store it, what to do when it changes, and usage when "the server is untrusted"
Layer 1: The Intuition
1.1 Remembering what someone looks like
The first time you visit a small shop, you remember what the owner looks like. Every time you visit thereafter, you will subconsciously take a look: it's the same person. If one day a stranger suddenly appears behind the counter claiming to be the owner, you will immediately become suspicious.
TOFU works exactly like this:
- During the first connection, record the other party's public key (or public key fingerprint);
- Every subsequent connection is compared with the recorded one;
- If they are inconsistent, stop and issue a loud warning.
1.2 What it prevents, and what it doesn't
| Scenario | TOFU Behavior |
|---|---|
| Attacker appears from the second encounter onwards (Man-in-the-Middle, server replaced) | Can detect |
| Attacker is present from the very first encounter | Cannot detect: You recorded the attacker's key |
| The other party legitimately changes their key (OS reinstallation, new phone) | Will trigger a false positive; requires manual confirmation |
Therefore, the value of TOFU lies in this: an attacker must be lying in wait from the very beginning, which is much harder than "interjecting at any time."
Layer 2: Real-World Use
- SSH: When connecting to a server for the first time, you are prompted with "The authenticity of host ... can't be established." After you answer
yes, the fingerprint is written to~/.ssh/known_hosts. If the fingerprint changes later, a prominentREMOTE HOST IDENTIFICATION HAS CHANGED!will appear and the connection will be refused. - Signal / WhatsApp Safety Numbers: If the other party's identity key changes (e.g., they switched phones), the chat will display "Safety number changed." To verify even the first encounter, scan the code in person (see "Out-of-band Verification").
- Mobile App Certificate Pinning: A banking app only accepts specific certificates or public keys from its own server. Even if a malicious root certificate is installed on the phone, a Man-in-the-Middle attack remains impossible.
- The failure of HPKP: Browsers once supported websites declaring "only recognize these specific public keys from now on" via HTTP headers (HPKP, 2015). As a result, many websites misconfigured it or lost their backup keys, effectively locking their own users out; attackers could also perform "ransomware pinning" by pinning a malicious public key. Around 2018, mainstream browsers gradually abandoned it in favor of Certificate Transparency.
- Key Transparency: A mechanism recently introduced by WhatsApp and iMessage that writes all users' public keys into a public, auditable log. Clients can check whether the server has "secretly swapped keys" for a specific person. The principle is similar to hash-chain audit logs.
Layer 3: Principles and Engineering
3.1 What to pin
| Choice | Pros | Cons |
|---|---|---|
| Pinning specific certificates | Most strict | Becomes invalid as soon as the certificate is renewed |
| Pinning public keys (SPKI fingerprint) | Can reuse the same key during renewal | Requires planning for key rotations |
| Pinning CAs | Flexible | Weak protection: Any certificate signed by that CA will be accepted |
In engineering, public keys are generally pinned, and a backup public key is pinned simultaneously (stored offline) to prevent locking oneself out if the primary key is lost. This was the primary lesson from the failure of HPKP.
3.2 Usage when "the server is untrusted"
TOFU has another lesser-known use case: preventing one's own server from being compromised.
Imagine a user stores important data in an app (such as a shared setting or a list), and the data resides on a server. If the server is compromised, an attacker can quietly modify the list. The countermeasure:
- Every item in the list is signed by a private key on the user's device;
- When the client receives the user's public key for the first time, it is pinned locally;
- Every time the list is read thereafter, it is verified using the locally pinned public key; if the public key provided by the server is inconsistent with the local one, an alarm is triggered.
In this way, the attacker either cannot modify the list (lacking the private key) or will be detected by the local pinning if they try to swap the public key as well.
3.3 What to do when it changes
- Never automatically accept a new key. Automatic acceptance is equivalent to having no pinning at all.
- Provide clear prompts: which value changed, when, possible legitimate reasons (reinstallation, device change), and illegitimate reasons (Man-in-the-Middle);
- Provide an out-of-band confirmation path (phone call, in-person QR scan) to update the pinned record only after confirmation.
3.4 The new device problem
When a new device is used, there are no local records, so the server must be "trusted for the first time" again. This window of vulnerability requires a fallback mechanism, such as entering a read-only period after a new device comes online (see "Cooling-off Period") and notifying the old device.
Summary
| Layer | Key points |
|---|---|
| Intuition | Remember the public key seen the first time; alarm if it changes |
| Application | SSH known_hosts, Signal safety numbers, App certificate pinning, Key transparency |
| Lessons | HPKP was deprecated due to configuration errors and lockout risks; always have a backup key |
| Advanced | Use local pinning to detect "your own server" being tampered with; use fallbacks for the new device window |