Why You Cannot Trust a Key You Were Handed
25.0 What this chapter gives you#
- You will be able to state the introduction problem in one sentence and explain why no amount of cryptography solves it on its own.
- You will be able to walk through a man in the middle attack that uses two key pairs, naming every message and every value the attacker substitutes.
- You will be able to say exactly what trust on first use gives you, exactly what it does not, and where the SSH host key model breaks.
- You will be able to read an OpenPGP certification signature, name its four types, and compute by hand whether a key counts as valid under the default rules.
- You will be able to explain in numbers why the web of trust could not scale to the public internet, and why a hierarchy could.
- You will be able to find the root certificates on a Linux, Windows, macOS or Android device, count them, and say who decided they should be there.
- You will be able to name the four root programmes that matter, the current version of each policy as of August 2026, and one requirement each enforces.
- You will be able to write a correct HTTP Public Key Pinning header, compute the pin value yourself from a certificate, and explain the two failure modes that killed the mechanism.
- You will be able to choose between trust on first use, a web of trust and a hierarchy for a system you are designing, and defend the choice with the properties of each.
- You will be able to recognize, in any protocol you are handed, the exact moment where authentication is imported from somewhere else rather than created.
Public key cryptography is the most useful invention in the history of computer security, and it has one hole in it that has never been closed. The mathematics gives us a pair of numbers, one of which can be shouted across a crowded room while the other stays secret, such that anything done with the first can only be undone with the second. From that one trick we get confidentiality without a shared secret, signatures anyone can check and nobody can forge, and authentication over a wire a hostile party controls end to end.
The hole is this. Every one of those guarantees is a statement about a key, not about a person. The mathematics will tell you, with certainty, that the message you received was signed by the holder of key number 4713 and by nobody else. It will not tell you that key 4713 belongs to your bank. Nothing in the algebra knows what a bank is. The binding between a key and a name is not a mathematical fact; it is a claim about the world, and claims about the world have to reach you over some channel, and every channel can be attacked. This is the introduction problem, and it is the subject of this chapter.
The three answers the industry has actually shipped are the three we will study. The first is to remember: write down the key the first time you see it and shout if it ever changes. That is what your SSH client does every day, and it is called trust on first use. The second is to ask around: let people sign each other’s keys, and follow the chain of signatures from someone you already know to someone you do not. That is the web of trust, and Phil Zimmermann built it into PGP in 1992. The third is to agree in advance on a small number of introducers whose keys everybody already has, and let those introducers vouch for everyone else. That is the hierarchy, and it is why your browser can connect to a site it has never seen and show no warning at all.
None of the three is correct in the way a proof is correct. Each moves the problem to a different place, and the engineering question is always the same: to where, and at what cost. The chapter before this one dealt with account recovery, the path that bypasses your authentication; the chapter after this one takes apart the certificate, the signed statement a hierarchy issues, field by field. Here we are concerned only with the question that comes before either. Somebody hands you a key. Why would you believe them.
The plain version#
A lock anyone can close and only one person can open#
Imagine a very unusual padlock. It comes open, and anybody who picks it up can snap it shut. Once shut it cannot be opened by snapping, by pulling, or by any amount of fiddling. It can only be opened by one specific small brass key, and there is exactly one of those in the world.
Meera has such a padlock. She keeps the brass key on a chain around her neck. The padlock itself she does not guard at all. She makes a hundred copies of the open padlock and leaves them in a bowl by her front door with a label that says “Meera”. Anybody may take one.
You want to send Meera a letter only she can read. You take a padlock from the bowl, put your letter in a steel box, and snap the padlock shut on it. You post the box. It can be stolen, photographed, dropped in a puddle, opened by nobody. When it reaches Meera she lifts the brass key off her neck and reads the letter. You and Meera never met and never agreed on a password. That is the whole of public key cryptography in one image. The open padlock is the public key. The brass key on the chain is the private key.
The same pair does a second job, running the other way. Suppose Meera wants to prove a letter came from her. A machine takes her brass key and a letter and stamps a wax seal on it. Anyone holding one of Meera’s open padlocks can hold it against the seal and see whether it fits. If it fits, the seal was made with Meera’s brass key and no other. That is a signature, and it is the job public keys do far more often than the locking job.
The stranger at the door#
You do not live next door to Meera. You have never seen the bowl. What actually happened is that a courier knocked and handed you an open padlock labelled “Meera”.
Consider what you know. You know that whoever made this padlock holds the only brass key that opens it. The metal guarantees that. You do not know that the maker is Meera. The courier could have bought a blank padlock, filed his own brass key for it, and written “Meera” on the label in a nice hand. Everything about the padlock will behave perfectly. It will snap shut, resist every attempt to force it, and open for exactly one key in the world. That key is around the courier’s neck. This is not a flaw in the padlock. It is a flaw in the story you told yourself about where the padlock came from.
It gets worse, because the courier carries letters in both directions. He gives you his own padlock labelled “Meera”, and gives Meera a second padlock of his own labelled with your name. You lock your letter using what you believe is Meera’s padlock. The courier opens it with his own key, reads it, copies it word for word, locks the copy with a genuine padlock taken from Meera’s bowl, and delivers it. Meera reads exactly what you wrote and replies. The courier does the same in reverse. Nothing is delayed, nothing is garbled, no seal fails to fit, and he reads every word in both directions for as long as he likes.
This is the man in the middle, and the thing to notice is that he broke nothing. He picked no lock, forged no key, guessed no password. He made sure each of you was handed the wrong padlock at the very beginning, and everything after that followed from good faith and good cryptography.
Three answers people actually use#
There is no clever escape using more padlocks. Whatever object the courier hands you, he could have made it himself. The only way out is to get at least one true fact about Meera’s padlock from somewhere the courier does not control. Three ways of doing that are used in practice.
The first is to remember. The first time a padlock labelled “Meera” arrives you accept it, and you scratch a mark on your doorframe recording exactly what it looked like. From then on you compare, and if a padlock labelled “Meera” ever looks different you stop and make a lot of noise. This does nothing for you on the first day and a great deal on every day after. If the courier was honest on day one he can never start cheating on day two hundred without being caught.
The second is to ask around. Meera takes her padlock to a party where everybody knows everybody. Her friend Arjun checks her identity card, examines the padlock, and makes a small engraving on it with his own private tool: Arjun says this padlock belongs to Meera. Ten other friends do the same. When a padlock labelled “Meera” reaches you, you look at the engravings. You do not know Meera, but you know Arjun and you already hold Arjun’s padlock from an occasion when you met him. The engraving fits Arjun’s padlock, so Arjun vouched for this one. If you do not know Arjun either, perhaps you know someone who does, and you follow the engravings back until you reach someone you met yourself.
The third is to agree in advance on a few trusted engravers. The town agrees there are, say, one hundred official notaries. Every citizen is given a sealed copy of all one hundred notary padlocks in a box they trust. When Meera wants a padlock strangers will accept, she goes to a notary, proves who she is, and the notary engraves it. Now anybody can check any padlock without knowing anybody. This is the arrangement your web browser uses, and the box you were given is the list of root certificates that shipped with your operating system.
Each answer has a price. Remembering costs you the first day. Asking around costs you a social network, and on a planet of eight billion people the chain of acquaintance you need very often does not exist. Agreeing on notaries costs you the notaries: any one of the hundred can engrave a padlock with anybody’s name on it, and if even one is careless or corrupt or burgled, the whole town is exposed.
The short number on the back of the lock#
One more piece of plain machinery. Padlocks are big. Comparing one against another byte for byte would mean reading a few hundred digits, and nobody reads a few hundred digits down a telephone.
So we use a shrinking machine. A padlock goes in one end and a short string of about forty-three characters comes out the other. Two properties matter. The same padlock always produces the same string, and nobody with all the computers in the world can build a different padlock that produces the same string. That short string is called a fingerprint.
Here is a real one. While writing this chapter I generated a key for an imaginary machine called build-01.kedbyte.example. This is its real fingerprint, produced on 17 August 2026 by the standard SSH tool, followed by the fingerprint of a second key generated at the same moment which will play the attacker throughout this chapter:
SHA256:J/pV9jAq8GQTcKQyBYZoFGqeY++codDN9Yipcu485Y4
SHA256:NXq8KZ2C+ztKGrzPf/qkHyHjBXnUSFzwG/v5EUDNps4
Look at the first three characters of each. If a colleague reads you the first string over the telephone and your computer shows the second, you know something is wrong in about four seconds. Every one of the three answers above is, underneath, a way of getting one trustworthy fingerprint into your hands: your doorframe holds it, your friends’ engravings vouch for it, or the notary list contains it.
Where the plain version stops being true#
The padlock is mostly used for signing, not for locking#
Putting a letter in a box and snapping a lock on it is how public key cryptography was explained in 1976 and how it is still taught. It is not what happens when you load a web page.
The honest version: on the modern web the server’s public key is almost never used to encrypt your data. It signs one message during the opening exchange, and that is all it does. The secrecy of the connection comes from a separate, temporary key agreement that both sides perform together and then throw away, so that if the server’s long-term private key is stolen next year an attacker who recorded this year’s traffic still cannot read it. Chapter 29 takes the handshake apart message by message.
This sharpens our question rather than softening it. If the public key’s only job is to sign one message, the entire security of the connection rests on whether that key belongs to the name in the address bar. The introduction problem is not one problem among several. On the web it is the problem.
Comparing fingerprints moves the problem, it does not remove it#
I said you could telephone a colleague and read the fingerprint aloud. Notice what that assumes: that you can recognize his voice, that the telephone network is not being manipulated, and that the number you dialled is really his. You have not created trust out of nothing. You have imported it from the telephone system and from your own ear, and both can be attacked. Voice cloning is now cheap and caller number spoofing has been cheap for twenty years.
The honest version: authentication is never manufactured, only transferred. Every scheme in this chapter takes a channel you already believe in and converts that belief into belief about a key. The design question is not “is this secure” but “which channel am I borrowing from, and does the attacker who worries me have access to it”. Trust on first use borrows from the assumption that nobody was attacking you the very first time. A root store borrows from the software update mechanism that put it on your machine, which is worth sitting with: your entire browsing security rests on the integrity of your operating system’s update channel.
Fingerprints have a second weakness, which is that people compare them badly. Dechand and colleagues at the University of Bonn, Technische Universitaet Braunschweig and Saarland University ran a study with 1047 participants, published at the 25th USENIX Security Symposium in 2016, comparing six textual ways of representing a key fingerprint. They found the hexadecimal representation everyone uses is the most vulnerable to an attacker who only has to match part of the string, because people check the beginning and the end and skip the middle.
Trust on first use does not protect the first use#
The name says it and people still get it wrong. The doorframe protects every connection except the one that mattered most, the one where you had no information at all. If the courier was already in place on day one, the doorframe now faithfully records the attacker’s padlock and will loyally warn you if the real Meera ever shows up.
The honest version: trust on first use converts an ongoing attack into a one-shot attack. That is real and useful and it is not authentication. An attacker present at the moment a relationship begins gets everything, and that moment is often predictable: a new employee’s first login happens on their first day, and a device’s first contact with its management server happens when it is switched on, often in a warehouse, on a network nobody is watching.
“My friends vouched for it” hides two different kinds of trust#
When Arjun engraves Meera’s padlock, one word is doing two jobs. There are two separate questions you might be asking. Do I believe this padlock really is Meera’s, because Arjun says so. And do I believe Arjun is careful about who he engraves for.
These are different beliefs about different people, and PGP keeps them in different places. The first is called validity and it is computed. The second is called owner trust, you assign it by hand key by key, and it is stored only on your own machine and shown to nobody. Confusing them is the commonest misunderstanding of the web of trust. Signing a key does not mean you trust its owner’s judgement about other people; it means you checked their identity document. There is a separate mechanism, a trust signature, for saying “and I also think this person is careful”, and almost nobody used it.
The honest version: a web of trust is two graphs on top of each other. One is public and made of signatures. The other is private, lives only in your own trust database, and is what actually decides whether your software will use a key without asking.
A few notaries means any one notary can vouch for anybody#
The hierarchy story sounds tidy. The part it leaves out is that the notaries are not divided up by subject. Any one of them can issue for any name. Nothing in the basic design says the Turkish notary may only vouch for Turkish names, or that the notary you actually chose is the only one who can vouch for you.
The consequence is arithmetic. Your security against a forged certificate for your bank is not the security of your bank’s certificate authority. It is the security of the weakest of every authority in the store. If your store holds 121 roots and 120 of them are run impeccably, your exposure is the 121st. The second half of this chapter lists six occasions between 2011 and 2015 on which exactly that happened, one of which ended with a certificate authority in bankruptcy inside three weeks. Name constraints, described in chapter 27, and Certificate Transparency, chapter 31, both help. Neither changes the shape: in a hierarchy you trust a set, and a set is as strong as its weakest member.
The lock symbol in the address bar does not mean what people think#
The plain version treated “the notary engraved it” as settling the matter. It settles a much narrower matter than users believe. When your browser shows a connection as secure, the claim is: the name I typed appears in a certificate, that certificate chains to a root in my store, the chain validates, and the server proved it holds the matching private key.
The honest version: that is a statement about the name, not about the site. It does not say the site is honest, that it is the company you have in mind, that your data is safe there, or that the company has any legal existence. A phishing site with a name one letter different from your bank’s gets identical treatment, for free, in ninety seconds, from a fully compliant certificate authority. Chapter 28 covers what a certificate authority actually checks.
The technical version#
The introduction problem, stated precisely#
Every guarantee public key cryptography offers has the same shape: a verifier who holds the public key learns something about the holder of the private key. A valid signature proves the signer held the private key and that the message has not changed by one bit. A successful key agreement proves the far end held it. In neither case does the mathematics produce a name, because names are not mathematical objects.
So we need a binding: an assertion that a particular identifier, such as a domain name, an email address or a host name, corresponds to a particular public key. And that assertion must reach the verifier over a channel that is authentic, meaning the verifier can tell where the data came from and whether it was modified in flight. The channel need not be confidential. It is perfectly acceptable for the whole world to watch you receive your bank’s public key, as long as nobody can change it on the way.
This asymmetry is the load-bearing beam of the field. You can build a confidential channel out of an authentic one. You cannot build an authentic channel out of a confidential one. Transport Layer Security is exactly the first of those: it takes an authentic channel, the pre-installed root certificates, and manufactures confidentiality on demand. It has no way to manufacture the authentic channel it started from, which is why that channel arrives on your device by a completely different route, inside the operating system image.
Diffie and Hellman saw the problem in the paper that started all of this. In “New Directions in Cryptography”, published in the IEEE Transactions on Information Theory in November 1976, section III describes the arrangement plainly: “The enciphering key E can be made public by placing it in a public directory along with the user’s name and address.” Then a sentence of caution: “It is crucial that the public file of enciphering keys be protected from unauthorized modification.” That is the introduction problem, named on the day the field was invented and left as an exercise. Two years later, in 1978, Loren Kohnfelder’s bachelor’s thesis at MIT proposed replacing the online public file with a signed offline object and gave it the name we still use, the certificate; chapter 26 takes that object apart field by field.
Three families of answer exist, and every deployed system is one of them or a blend.
| Model | Where the binding comes from |
|---|---|
| Trust on first use | Your own memory of last time |
| Web of trust | Peers who signed each other |
| Hierarchy | Pre-installed trust anchors |
A trust anchor is a public key a verifier accepts without checking anything, because it arrived by some out-of-band route. Every system has at least one. There is no such thing as a system with zero trust anchors; there are only systems that have hidden where theirs came from.
The man in the middle with two key pairs, step by step#
Alice is an engineer on her first day. Bob is the build server, build-01.kedbyte.example. Mallory sits on the network path between them, which in practice means she controls the wireless access point, has poisoned the local address resolution cache, runs the router, has hijacked the route by which traffic reaches that network, or answers the name lookup with her own address.
The keys below are real Ed25519 keys generated on 17 August 2026 for this chapter, and are published here precisely because they are worthless. The server’s genuine public key, wrapped across two lines because it does not fit on one, then its fingerprint, which is the SHA-256 hash of the key blob in base64 with the padding stripped:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDslTO/gncoaM24bAUS
IbZ/vtX+D7liko+l5/3JfBbeA build-01.kedbyte.example
256 SHA256:J/pV9jAq8GQTcKQyBYZoFGqeY++codDN9Yipcu485Y4
Mallory’s key, generated three seconds later on the same machine, and its fingerprint:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN8QHPL/9+rkMmTLuq2
NqIwAOOMF/QWxNujX650AsUhw mallory
256 SHA256:NXq8KZ2C+ztKGrzPf/qkHyHjBXnUSFzwG/v5EUDNps4
Nothing about Mallory’s key is weaker: both are 256-bit Ed25519 keys from the same tool and the same entropy source. Mallory runs two separate cryptographic sessions and bridges them.
Alice Mallory Bob
| | |
1 | open connection | |
|-------------------->| |
2 | | open connection |
| |--------------------->|
3 | | Bob's real key |
| |<---------------------|
4 | Mallory's key, | |
| labelled "Bob" | |
|<--------------------| |
5 | session set up | session set up |
|<===================>|<====================>|
6 | plaintext in | decrypt, log, |
|-------------------->| re-encrypt |
| |--------------------->|
-
Alice’s client opens a connection to what it believes is build-01. The packets reach Mallory, who simply answers. She has forged nothing yet.
-
Mallory opens her own connection to the real build-01. From Bob’s point of view this is an ordinary client at an ordinary address.
-
Bob sends his real host key, the one whose fingerprint begins J/pV9j. Mallory keeps it, because she must run a genuine session with Bob.
-
Mallory sends Alice her own host key, the one whose fingerprint begins NXq8KZ. She sends it in the same protocol field, in the same format, at the same point in the handshake. There is no flag in the protocol that says “this key is a substitute”. What Alice receives is a well-formed, correctly typed host key.
-
Alice’s client completes the key exchange with Mallory, who holds the matching private key, so every proof-of-possession step succeeds. Alice is now in a fully encrypted, integrity-protected session whose far end is Mallory. Simultaneously Mallory completes a second, genuine key exchange with Bob using Bob’s real key.
-
Alice types her password, presents her private key, or pushes her code. Mallory decrypts with the first session’s keys, records, and re-encrypts with the second session’s keys. Bob sees a correct authenticated session; Alice sees a correct encrypted session. Both are right, and neither is talking to whom they think.
| Party | Believes it is talking to | Actually talking to |
|---|---|---|
| Alice | build-01 | Mallory |
| Bob | Alice | Mallory |
| Mallory | Alice and Bob | Alice and Bob |
Every cryptographic check passed. No algorithm was broken, no random number was predictable, no certificate expired, no downgrade occurred. The attack lives entirely in step 4, and step 4 is not a cryptographic operation. It is a delivery. That is why every mitigation in this chapter attacks step 4 and none attacks the cryptography: trust on first use compares the key in step 4 with a stored copy, the web of trust demands signatures on it, and the hierarchy demands that it arrive wrapped in a certificate signed by a pre-installed anchor.
One historical attempt deserves naming. In 1984 Ronald Rivest and Adi Shamir published “How to Expose an Eavesdropper” in Communications of the ACM, volume 27, number 4. Their interlock protocol has each side send only the first half of its encrypted message and wait for the other’s first half before sending the second, so a relaying attacker must invent a plausible first half before she can read the real one, and a wrong guess makes the conversation visibly fall apart. It detects a live relay and tells you nothing about whose key you hold. Detection is not authentication.
Trust on first use, and exactly what SSH host keys give you#
Secure Shell was written by Tatu Ylonen at Helsinki University of Technology in 1995 after a password-sniffing attack on the university network, and it made a decision most of the industry then copied: it shipped with no infrastructure at all.
RFC 4251, “The Secure Shell (SSH) Protocol Architecture”, January 2006, sets out the position in section 4.1. It offers two models. In the first, “The client has a local database that associates each host name (as typed by the user) with the corresponding public host key.” In the second, “The host name-to-key association is certified by a trusted certification authority (CA),” and the client then needs only the CA’s key. The specification is candid about the compromise it then makes: implementations may allow an unverified first connection, because otherwise nothing would ever get deployed, but they “SHOULD NOT normally allow such connections by default, as they pose a potential security problem.” The first model won, with the exception switched on, and that combination is trust on first use, sometimes called leap-of-faith authentication.
The local database is the known_hosts file: one line per record, with the host pattern, the key type and the base64 key blob. Here is a real one for our server, wrapped for the page:
build-01.kedbyte.example ssh-ed25519 AAAAC3NzaC1lZDI1NT
E5AAAAIDslTO/gncoaM24bAUSIbZ/vtX+D7liko+l5/3JfBbeA
The host name can be hashed with a per-line salt so that a stolen known_hosts file does not hand an attacker a map of everywhere you connect. That is controlled by HashKnownHosts, whose upstream default is no while several distributions patch it to yes; an implementation detail, not a standard, so check rather than assume.
The first connection produces this prompt, quoted from the message strings compiled into OpenSSH 9.6p1:
The authenticity of host 'build-01 (192.0.2.10)' can't be
established.
ED25519 key fingerprint is
SHA256:J/pV9jAq8GQTcKQyBYZoFGqeY++codDN9Yipcu485Y4.
This key is not known by any other names.
Are you sure you want to continue connecting
(yes/no/[fingerprint])?
That third option, typing the fingerprint instead of “yes”, lets an administrator holding the correct value on a printed sheet paste it and have the machine compare rather than the eye. It is the most under-used feature in OpenSSH.
If the stored key fails to match, the client produces the warning every engineer has seen and most have cleared without reading:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now
(man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ED25519 key sent by the remote
host is
SHA256:NXq8KZ2C+ztKGrzPf/qkHyHjBXnUSFzwG/v5EUDNps4.
Add correct host key in /home/alice/.ssh/known_hosts to
get rid of this message.
That is exactly Mallory’s fingerprint from the previous section. Trust on first use did its job: it caught step 4, on every day except the first.
Client behaviour is governed by StrictHostKeyChecking, whose values as documented in the current OpenSSH ssh_config manual page are:
| Value | New host | Changed key |
|---|---|---|
| yes | Refuse | Refuse |
| accept-new | Add silently | Refuse |
| ask (default) | Prompt user | Refuse |
| no or off | Add silently | Allow |
The accept-new value arrived in OpenSSH 7.6, released 3 October 2017, and it is the setting most automation should use: it removes the interactive prompt that scripts cannot answer while keeping the protection that matters. Setting the option to no, which a great deal of continuous integration configuration does, turns the mechanism off entirely and leaves you with encryption to an unknown party.
Two further pieces of machinery matter. Since OpenSSH 6.8, released 18 March 2015, the default fingerprint format is SHA-256 in base64 rather than MD5 in hexadecimal, with the algorithm name as a prefix. The same release added the hostkeys@openssh.com extension, by which a server tells an authenticated client about all of its host keys so the client can record them. The client side is UpdateHostKeys, which the manual page says is “enabled by default if the user has not overridden the default UserKnownHostsFile setting and has not enabled VerifyHostKeyDNS”. This solves rotation, and because it is bootstrapped from an existing trusted key it inherits whatever the first connection gave you and cannot improve on it. The other piece is SSHFP, RFC 4255, January 2006, which publishes the fingerprint as a DNS record checked by the client option VerifyHostKeyDNS. That is a different trust model in an SSH costume, borrowing authenticity from DNSSEC, and it is only as good as DNSSEC deployment on that zone.
| It gives you | It does not give you |
|---|---|
| Detection of key change | Any safety on first contact |
| No infrastructure at all | A story for key rotation |
| Zero cost per new host | Protection at scale |
| A real audit trail | A signal users still read |
The last row deserves the emphasis. In a fleet where servers are rebuilt several times a week the warning fires constantly for innocent reasons, and the remedy taught in every operations team is to delete the offending line and reconnect, at which point the mechanism has been trained out of existence. The fix is SSH certificates, where a small local authority signs host keys and clients trust only that authority: the second model from RFC 4251 section 4.1, and the hierarchy idea inside one organization.
The web of trust: certification signatures, trust levels and arithmetic#
Philip Zimmermann released PGP 1.0 in June 1991 by posting it to Usenet, which produced a three-year federal criminal investigation into whether he had violated arms export controls. The United States Attorney for the Northern District of California closed it on 12 January 1996 with a letter stating that Zimmermann “will not be prosecuted in connection with the posting to USENET in June 1991 of the encryption program Pretty Good Privacy”. The mechanism this chapter cares about arrived in the next version. In his own account, published as chapter 7 of the O’Reilly collection Beautiful Security in 2009, Zimmermann writes that PGP 2.0 replaced the cipher and “introduced the PGP trust model in a state that was close to its RFC 1991 form”.
The wire format went through four specifications: RFC 1991 in 1996, RFC 2440 in 1998, RFC 4880 in November 2007, and RFC 9580 in 2024, which obsoletes RFC 4880 along with RFC 5581 and RFC 6637. RFC 4880 is what most deployments implement and is cited here; for new code in 2026, read RFC 9580, because several packet layouts changed.
The unit of the web of trust is a signature made by one key over another key’s user identifier. RFC 4880 section 5.2.1 defines four certification types, distinguished by how hard the signer claims to have looked:
| Type | Name | Assertion made |
|---|---|---|
| 0x10 | Generic certification | No claim about checking |
| 0x11 | Persona certification | No verification done |
| 0x12 | Casual certification | Some casual checking |
| 0x13 | Positive certification | Substantial checking |
Almost every signature in the wild is 0x10 or 0x13, and the difference is enforced by nothing. It is a self-declaration, checkable by nobody.
Certification says “this key belongs to this person”. It does not say “this person is careful”. For that, RFC 4880 section 5.2.3.13 defines the trust signature subpacket, carrying two octets. The first is the trust level: 0 means an ordinary validity signature, 1 asserts the signed key is “a valid trusted introducer”, 2 asserts it may itself designate introducers, and so on. The second is the trust amount in the range 0 to 255, where the specification says “values less than 120 indicate partial trust and values of 120 or greater indicate complete trust”. Section 5.2.3.14 adds a regular expression subpacket so an introducer can be trusted only for identifiers matching a pattern, which is the same idea as the name constraints chapter 27 describes for certificates. Almost nobody used either. The trust signature was the mechanism by which the web of trust could have become a delegated hierarchy, and it was left on the shelf.
What decides whether your software will use a key is a local computation. GnuPG keeps a private trust database in which you assign each key an owner trust value of unknown, none, marginal, full or ultimate. Your own keys get ultimate. It then computes validity using three parameters whose defaults are documented in the GnuPG manual:
| Option | Default | Meaning |
|---|---|---|
| completes-needed | 1 | Fully trusted signers needed |
| marginals-needed | 3 | Marginally trusted needed |
| max-cert-depth | 5 | Longest chain allowed |
A key becomes valid if it carries a certification from at least one key you marked fully trusted, or from at least three you marked marginal, within a chain of no more than five steps from your own key.
Work it. You are Alice. You met Arjun in person, compared his fingerprint against a card he handed you, signed his key and set his owner trust to full. You also met Priya, Sanjay and Fatima at a conference, signed their keys, and set each to marginal because you do not know how careful they are. Meera’s key now arrives carrying certifications from Priya, Sanjay and Fatima but not from Arjun. Fully trusted signers: zero, fewer than the one required. Marginally trusted signers: three, which meets the requirement exactly. Meera’s key is valid, at depth 2, well inside the limit of five, and your software will encrypt to it without asking you anything.
Change one thing. Fatima has not signed it; only Priya and Sanjay have. Now you have two marginal signatures where three are needed and no full ones, so the key is not valid and GnuPG will warn before using it. The listing keeps the two ideas in separate columns, and this is what confuses newcomers:
pub ed25519 2026-08-17 [SC]
fingerprint of Meera's key here
uid [ full ] Meera <meera@example.org>
trust: unknown validity: full
The bracketed word is computed validity, the answer to “is this really her key”. The word after “trust:” is owner trust, the answer to “would I believe her about somebody else’s key”, set by you alone and shared with nobody. A key can be fully valid and completely untrusted, and that is the normal case: you are confident it is her key and have no opinion about her diligence.
Why the web of trust did not scale#
It is tempting to say it failed because it was hard to use. That is true and shallow. It failed for five specific reasons, and each tells you something a trust model has to provide.
The first is connectivity. The model needs a certification path between you and the party you want to reach, and for a person visiting a website they have never heard of, run by a company in a country they have never visited, no such path exists and none ever will. Zimmermann said so himself in that 2009 chapter: the web of trust “works at its best with groups of people who have some connections. It does not work well with a large, ubiquitous network like the Internet.” He estimated it scales “excellently at the low end, up to a few thousand people”. The measurements agree. Henk Penning’s long-running analysis of the strong set, the largest group of OpenPGP keys in which a path exists between any two members, showed growth from roughly 18,000 keys in early 2003 to roughly 62,000 at the start of 2018, then a fall to roughly 57,500 by May 2019; a paper by Gunnar Wolf and Jorge Luis Ortega-Arjona published in September 2022 puts it at about 60,000. Set that beside the hundreds of millions of names holding publicly trusted certificates and the gap is three orders of magnitude and a different shape of problem.
The second is that the identifier is wrong. OpenPGP binds keys to human identities, usually an email address with a display name. The web needs keys bound to service names, and there is no natural person to hold a key signing party for www.kedbyte.example.
The third is revocation. Certifications are published by pushing them to key servers, and the historical network, SKS, was deliberately built append-only so that no government could compel deletion. That property became the vulnerability. In late June 2019 an attacker attached enormous numbers of signatures to the certificates of two well-known contributors, Robert J. Hansen and Daniel Kahn Gillmor. Hansen’s certificate accumulated, in his own words, “just short of 150,000 signatures”, enough to make GnuPG hang for minutes or crash outright on import. Nothing could be deleted, because deletion had been designed out. Hansen’s advice was to abandon the network for the keys.openpgp.org server, which validates email addresses and does not accept third-party signatures. That was the end of the global web of trust as an operating system, and it came not from a cryptographic break but from a design decision made two decades earlier for good reasons.
The fourth is privacy. The signature graph is public by construction, so publishing it publishes a social network: who met whom, at which conference, in what year. For journalists, dissidents and their sources, the people the tool was built for, that is a serious and intrinsic harm.
The fifth is that it asks the wrong thing of users. Assigning owner trust requires a judgement about another person’s operational discipline, made once, in advance, with no feedback, and every practitioner account describes the same outcome: the step is skipped and the software falls back to asking.
None of this makes the web of trust worthless. In small groups with existing relationships it is the correct tool, and it is still how Debian developers authenticate to their own project. It is a local answer that was pressed into service as a global one.
The hierarchy: a few introducers everybody already has#
The hierarchy starts from an observation about counting. Suppose N parties might need to authenticate to each other. Under a pure peer model the number of introductions needed grows with the square of N, and each is a human act. Under a hierarchy you distribute R anchor keys to every party once, and then each party needs exactly one act of vouching. The human work falls from order N squared to order N, and the pre-distribution of R keys rides on a channel that already exists.
| Model | Introductions needed |
|---|---|
| Peer, everyone to everyone | Order N squared |
| Web of trust with paths | Fewer, but paths may not exist |
| Hierarchy with R anchors | R pre-installed, then N |
The picture is a fan, not a mesh:
web of trust hierarchy
============ =========
A ----- B R (already on your
| \ / | /|\ device before you
| \ / | / | \ ever used it)
| / \ | / | \
C ----- D S1 S2 S3
every pair needs each server needs one
a path between them signature from R
The pre-installed keys are trust anchors. On the public web they are root certificates, self-signed, whose real content is a public key plus a name. Real deployments insert one or more intermediate keys between root and server so the root’s private key can stay offline in a safe; chapter 27 covers how a chain is built and validated, and chapter 26 covers what is inside the signed statement.
What this buys is enormous. A browser that has never seen kedbyte.example, on a device that has never been on that network, connecting from an airport, verifies the binding with no interaction, no prior relationship and no extra round trip. Nothing else on this list can do that.
What it costs is that every anchor can vouch for every name. Your bank chose one certificate authority; your exposure is to all of them. If your store holds 121 roots, an attacker needs the least careful one of the 121, and the resulting certificate is accepted with no visible difference from the real one. Chapter 27 describes name constraints, which would fix this if widely deployed, and chapter 31 describes Certificate Transparency, which makes misissuance visible afterwards. Both are real improvements layered on top; neither changes the shape.
The honest version: the hierarchy does not solve the introduction problem. It relocates it, once, to the moment your operating system was installed, and amortizes that single solved introduction across every connection you will ever make. That is superb engineering and not a proof of anything.
Where the roots actually live, and who decides what is in them#
| Platform | Where the anchors live |
|---|---|
| Debian, Ubuntu | /etc/ssl/certs and NSS |
| Red Hat, Fedora | /etc/pki/ca-trust |
| Windows | Registry root store and CTL |
| macOS, iOS | Keychain System Roots |
| Android 14 and later | Conscrypt module and system |
| Firefox | Its own NSS database |
| Chrome | Chrome Root Store |
On a Debian-family system the bundle is plain text you can read and count:
grep -c "BEGIN CERTIFICATE" /etc/ssl/certs/ca-certificates.crt
ls /usr/share/ca-certificates/mozilla | wc -l
openssl x509 -noout -subject -dates \
-in /usr/share/ca-certificates/mozilla/ISRG_Root_X1.crt
On the Ubuntu 24.04.4 machine used to write this chapter, on 17 August 2026, the first command returned 152 and the second returned 147. The package supplying them was ca-certificates version 20240203, a snapshot of Mozilla’s store taken on 3 February 2024, still in service two and a half years later. That gap is not a bug; it is what a long-term support distribution means. It is also the most under-appreciated fact about trust stores: the set of keys your server trusts is frozen at the date of the package and drifts further from the browsers’ view every month.
Compare Mozilla’s current store. The curl project publishes a straight conversion of Mozilla’s server-authentication anchors and records the count at each revision:
| Bundle date | Root certificates |
|---|---|
| 4 November 2025 | 148 |
| 19 March 2026 | 145 |
| 16 July 2026 | 119 |
| 13 August 2026 | 121 |
The loss of roughly twenty-five roots between March and July 2026 is policy taking effect. Section 7.4 of the Mozilla Root Store Policy says that for a root trusted for server authentication, “Mozilla will remove the websites trust bit when the CA key material is more than 15 years from the CA key material generation date”, with 18 years for the secure email bit. Section 7.5 says all roots added after 15 March 2025 will be trusted for either server authentication or email, never both. A generation of roots created in the late 2000s is aging out on a published schedule, and operators were told to apply for replacements at least two years ahead.
The policies are the answer to “who decides”. Four programmes matter, and as of August 2026 they stand as follows.
Mozilla publishes the Mozilla Root Store Policy; version 3.1 took effect on 1 July 2026. Section 3.1 requires that “Before being included and at least annually thereafter, CA operators MUST obtain certain audits for their root certificates and all intermediate certificates that are technically capable of issuing working server or email certificates.” Section 7.3 reserves to Mozilla the right to disable or remove a certificate “at any time and for any reason”. Mozilla’s store matters far beyond Firefox, because it is the store most Linux distributions, language runtimes and container images ultimately ship.
Microsoft runs the Microsoft Trusted Root Program, whose requirements page was last revised on 28 April 2026. Requirement 1 obliges participants to provide evidence of a qualifying audit “for each root, unconstrained subordinate CA, and cross-signed certificate, before conducting commercial operations and thereafter on an annual basis”. Requirement 5 requires annual disclosure of the full hierarchy through the Common CA Database. Roots must be self-signed, must be valid for between 8 and 25 years from submission, may not issue new 1024-bit RSA certificates, and must use RSA 2048 or the NIST P-256, P-384 or P-521 curves with SHA-2 digests; certificates must be revoked within 24 hours of a Microsoft request. Windows does not keep all these roots on disk but fetches them on demand through the automatic root update mechanism, which is why a freshly imaged Windows machine with no network access can fail to validate a chain that works everywhere else.
Google runs the Chrome Root Program, policy version 1.8, last updated 5 February 2026. Section 1.2.1 caps the number of roots one operator may have: “If a CA Owner already has two (2) or more self-signed root CA certificates included in the Chrome Root Store, the Chrome Root Program will only accept a new CCADB Root Inclusion Request to replace an existing certificate”, a rule the policy calls one in, one out. The programme also applies its own metadata-based name constraints to roots in its store, imposed by the browser rather than encoded in the certificate. Chrome began using its own store rather than the platform’s with Chrome 105 on Windows and macOS, released 30 August 2022, with other platforms following.
Apple runs its own root programme and publishes the list of roots in its operating systems. [UNVERIFIED: the current version identifier and effective date of the Apple Root Certificate Program requirements as of August 2026.] All four programmes coordinate through the Common CA Database, where operators disclose hierarchies, audits and incidents once rather than four times.
Two platform details change the threat model on real devices. Applications targeting Android 6.0, API level 23, and lower trusted certificates the user had installed themselves; from Android 7.0, API level 24, the default configuration trusts only system anchors, which is why installing an interception certificate on a modern Android phone no longer reveals most application traffic. And from Android 14 the root trust store moved into the Conscrypt module, updatable through the Mainline mechanism rather than only through a full operating system release. The Android documentation is explicit: “Prior to Mainline, Android stored certificates in the system partition and updated them with every Android release. Now with Mainline, it is possible to update certificates more frequently.”
The corporate case is where most readers will meet a deliberate man in the middle. An enterprise running a TLS-inspecting proxy installs its own root on every managed device, making the proxy a legitimate anchor for every name. It is the attack from earlier in this chapter, run with consent, and the security of every connection on that network is now the security of that one appliance.
When a trust anchor goes wrong#
The weakest-link property is not hypothetical. Six incidents in five years reshaped the industry.
| Date | Party | Failure |
|---|---|---|
| March 2011 | Comodo reseller | Nine forged certificates |
| July 2011 | DigiNotar | Total compromise |
| February 2012 | Trustwave | Sub-CA sold for inspection |
| December 2013 | ANSSI chain | Google names issued |
| February 2015 | Komodia, Superfish | Shared private key |
| March 2015 | CNNIC, MCS Holdings | Unconstrained sub-CA |
On 15 March 2011 an attacker used the credentials of a compromised Comodo registration authority partner to request nine certificates in a two-hour window, for addons.mozilla.org, login.live.com, mail.google.com, www.google.com, login.yahoo.com three times, login.skype.com, and one for the name “global trustee”. Mozilla hard-coded a blacklist of the serial numbers into Firefox and shipped it on 22 March 2011.
DigiNotar was worse in every dimension. The Dutch certificate authority detected an intrusion on 19 July 2011 and did not disclose it. On 28 August 2011 users in Iran began seeing certificate errors, and by 30 August the breach was public. Fox-IT’s investigation, Operation Black Tulip, identified at least 531 misissued certificates; the fraudulent wildcard certificate for Google’s domains had been issued on 10 July 2011. Browsers removed DigiNotar’s roots on or around 29 August 2011, and the Haarlem court declared the company bankrupt on 20 September 2011. Three weeks from disclosure to insolvency.
In February 2012 Trustwave disclosed that it had issued a subordinate certificate authority certificate to a customer for a data loss prevention appliance that intercepted TLS inside that customer’s network. The certificate was unconstrained, so it could sign for any name on the internet, and its private key sat in a device on a corporate network. Trustwave revoked it and Mozilla asked every CA in its programme to revoke any similar certificates. Nobody had broken in; the capability had been sold.
Late on 3 December 2013 Google became aware of unauthorized certificates for several of its own domains, chaining back to ANSSI, the French network and information security agency, from an intermediate used in a traffic inspection appliance on a private network.
In February 2015 the CERT Coordination Center published vulnerability note VU#529496 on the Komodia Redirector with SSL Digestor, the interception library behind the Superfish advertising software pre-installed on Lenovo consumer laptops. The root certificates involved “use trivially obtainable, publicly disclosed, hard-coded private keys”, and because the same private key was on every affected machine, anyone who extracted it once could impersonate any website to all of those users. The note lists eleven affected products beyond Superfish.
In March 2015 Mozilla revoked trust in an intermediate that CNNIC had issued to MCS Holdings, describing it as a test certificate with two weeks of validity that the customer instead loaded into a firewall performing TLS interception, whereupon the device generated certificates for domains the customer did not own. Mozilla added it to OneCRL in Firefox 37, and both Google and Mozilla later stopped trusting new CNNIC certificates.
Read the list again. Two were break-ins. Four were the trust anchor working exactly as designed, for a customer who wanted to intercept traffic. The failure mode of a hierarchy is not usually theft. It is authorized issuance to someone who should not have had it.
Pinning: HPKP, and the ways it failed#
The obvious response to a store of 121 anchors any of which can vouch for your name is to say: I know which key my site uses, so let the client refuse everything else. That is pinning, and it worked. Chrome shipped a hard-coded list of expected keys for Google’s own properties, compiled into the browser, and it was that list which turned the DigiNotar forgery from a silent, perfectly valid certificate into a visible error and a bug report. Static, vendor-compiled pinning is still in every major browser.
The limitation is that a hard-coded list contains only sites important enough for the vendor to add by hand. HTTP Public Key Pinning was the attempt to let any site declare its own pins over the wire. It was published as RFC 7469 in April 2015, by Chris Evans, Chris Palmer and Ryan Sleevi of Google.
The mechanism is a response header, and the pinned value is a SHA-256 hash of the certificate’s Subject Public Key Info structure, base64 encoded. Appendix A of the RFC gives the recipe. Here it is as a real command run against a certificate generated for this chapter, a P-256 certificate for www.kedbyte.example with serial 02EA4D674F853EAD40B75484FDA44DFB2A07A9B3, valid from 17 August 2026 to 15 November 2026:
openssl x509 -in site.crt -pubkey -noout |
openssl pkey -pubin -outform der |
openssl dgst -sha256 -binary |
openssl enc -base64
That produced the first pin below; a second key generated as the spare produced the second:
AJqdAunv4O0Kwch1EkFDMWAXfACr7L9qziYBcq5otYU=
drv6B1V9ULpea2JfB7cKnj/dygcZ6S7etyH1O+AhyXw=
The header carrying them, with the directives defined in section 2.1 of the RFC:
Public-Key-Pins: max-age=5184000;
pin-sha256="AJqdAunv4O0Kwch1EkFDMWAXfACr7L9qziYBcq5otYU=";
pin-sha256="drv6B1V9ULpea2JfB7cKnj/dygcZ6S7etyH1O+AhyXw=";
includeSubDomains;
report-uri="REPORTING-ENDPOINT"
| Directive | Effect |
|---|---|
| pin-sha256 | One acceptable SPKI hash |
| max-age | Seconds to remember |
| includeSubDomains | Apply to all subdomains |
| report-uri | Where to send failures |
Two design points repay attention. The pin covers the public key, not the certificate, so you may renew a certificate as often as you like and the pin still matches provided the key pair is unchanged. And section 4.3 makes a spare mandatory: “UAs MUST require that hosts set a Backup Pin”, so a header carrying only pins that match the current chain is ignored. The point of the backup is that the spare key is not in use anywhere, so compromise of the live key does not compromise it.
The RFC saw the danger and wrote it down. Section 4.1 discusses capping max-age, section 4.5 is titled Hostile Pinning, and Appendix B is deployment guidance. None of it was enough, for three reasons that are now textbook.
The first the community named HPKP suicide. Lose every pinned key, through a hardware security module failure, a mis-scripted rotation, or simply losing the spare nobody ever tested, and every browser holding your pins refuses to connect until max-age expires. There is no override, no click-through, and no way to push a correction, because the correction would have to arrive over the connection the browser refuses to make. A site with a sixty-day max-age that lost its keys was off the internet for its returning visitors for sixty days.
The second is hostile pinning, sometimes called RansomPKP. An attacker with an hour of control over your server or your domain can set pins for keys only they hold, with a long max-age. When you regain control, your visitors’ browsers enforce the attacker’s pins against your real certificate and lock them out. A brief compromise becomes a long outage, and the protective mechanism is the weapon.
The third is that almost nobody deployed it, so vendors were carrying a dangerous feature for a rounding error of the web. Scott Helme, who ran the best-known survey of security headers, published “I’m giving up on HPKP” on 24 August 2017, describing those failure modes and the very low usage rate even among the top million sites.
Google announced deprecation and then removal. The Chrome 72 deprecations and removals note, published in December 2018 for a release that reached stable in January 2019, gives the reasoning plainly: the feature had “very low adoption” and introduced “denial of service and hostile pinning”. Mozilla followed; dynamic HPKP was disabled in Firefox 72, in Nightly in November 2019 and at release in January 2020. Mozilla noted that only Opera, Android WebView and Samsung Internet had implemented it alongside Chrome, that Firefox’s built-in static pin list remains enabled and covers Mozilla’s own services along with Google, Facebook, Twitter, Dropbox and Tor, and that DNS Certification Authority Authorization was the better alternative, with “much larger adoption” and none of the drawbacks.
One honest note on status. As of August 2026 the IETF datatracker still lists RFC 7469 as a Proposed Standard published in April 2015, not obsoleted by any document and not reclassified as Historic. The specification is alive on paper and dead in every browser that matters. If you find HPKP headers in a configuration file today they are inert, and you should delete them.
What replaced pinning#
Nothing replaced it with a single mechanism, because HPKP was doing several jobs at once. Four things took over between them.
Browser-managed static pinning stayed and is still enforced. The difference is who holds the risk: the pins live in the browser’s source tree, the vendor controls the release schedule, and a mistake is caught before it ships. It is available only to sites the vendor will carry.
Certificate Transparency did the detection job better. Every publicly trusted certificate must now be logged in public, append-only logs, a requirement Chrome applied to certificates issued after 30 April 2018 with enforcement from Chrome 68, and chapter 31 is devoted to it. A forged certificate for your domain became something you can discover by watching a log rather than something you can only prevent by pinning: detection replaced prevention because prevention was too brittle. The proof that the substitution was believed is Expect-CT, a header letting a site ask browsers to enforce logging for its own certificates, published as RFC 9163 in February 2022 as an Experimental specification and removed from Chrome at milestone 107 because “Chrome requires CT on all public websites now, so there is no security value to Expect-CT anymore”.
Certification Authority Authorization, RFC 8659, did the restriction job from the other end. Instead of the site telling clients which keys to accept, the domain owner publishes a DNS record telling certificate authorities which of them may issue at all. It is not enforced by the client, so it does not stop a malicious CA, and it does stop the far commoner failure of an honest CA issuing to the wrong requester. Chapter 28 covers it.
Application-level pinning survived and thrives, because inside an application the fatal objection disappears. On Android the network security configuration supports a pin-set element with an expiration date, and the documentation carries the same backup rule HPKP had: “when using certificate pinning, you should always include a backup key so that if you are forced to switch to new keys or change CAs your app’s connectivity is unaffected. Otherwise, you must push out an update to the app to restore connectivity.” Apple’s platforms offer an equivalent through pinned-domain declarations in the application’s property list. This is safe where HPKP was not because client and server ship from the same organization on a release train it controls, so the recovery path is an application update, which exists, rather than a browser cache expiry, which cannot be hurried.
DANE, RFC 6698, published in 2012, publishes the acceptable certificate or key in DNS, secured by DNSSEC. No major browser implemented it for the web; it found a real home in mail transport between servers, where the clients are a small number of well-maintained systems rather than a billion browsers.
The principle to carry away: pinning is appropriate exactly when the party that sets the pin and the party that enforces it can be updated together. Inside an application, a device fleet or a service mesh, pin freely. Across the open web, do not.
The three models compared#
| Model | Anchor comes from | Deployed in |
|---|---|---|
| Trust on first use | First contact, stored | OpenSSH known_hosts |
| Web of trust | Peer certifications | Debian keyring, OpenPGP |
| Hierarchy | Pre-installed roots | Web PKI, S/MIME, code |
The comparison that decides a design is the failure mode, and after that the cost of adding a party:
| Model | Fails when | Cost to add a party |
|---|---|---|
| Trust on first use | Attacker is there first | Nothing, and no safety |
| Web of trust | No path, careless signer | A human meeting |
| Hierarchy | Any one anchor misbehaves | One issuance, minutes |
Signal and WhatsApp are the largest deployment of the first model on the planet. Both bind keys on first contact, expose a safety number that two users can compare in person or over a video call, and warn when it changes. That is trust on first use with an optional manual upgrade, at a scale of billions, and it works because the failure mode of a messaging application differs from that of a bank: an attacker present at first contact between two friends learns their conversation, and cannot spend their money.
For a system you are designing, one question settles most of the choice. Can you get one authentic value to the client before it first connects, through an installer, a device image, a configuration management system or a printed sheet? If yes, use a hierarchy with your own anchor, and enjoy the name constraints the public web cannot use. If no, but the population is small and the parties can meet, a web of trust is honest about what it is. If no to both, trust on first use is what remains, and you should say so in your threat model in those words rather than describing the system as authenticated.
25.98 Common wrong ideas#
Wrong: If the connection is encrypted, nobody can read it. Right: Encryption guarantees only that the holder of the matching private key can read it, and a man in the middle who supplied you with her own public key is that holder, which is why every model here attacks the delivery of the key rather than the cipher.
Wrong: A man in the middle attack means the cryptography was broken. Right: In the standard attack nothing is broken; the attacker runs two complete, correct, authenticated sessions, one with each victim, using two key pairs she generated herself, decrypting on one side and re-encrypting on the other.
Wrong: Trust on first use protects you from interception. Right: It detects a key change on every connection after the first and gives you nothing on the first, so an attacker present when the relationship begins gets everything, and the stored record then names the attacker’s key as the legitimate one.
Wrong: Signing somebody’s PGP key means you trust them. Right: Signing asserts only that you checked this key belongs to this person, which OpenPGP calls validity; whether you believe their judgement about other keys is a separate value, owner trust, set privately and never published.
Wrong: My site’s security depends on the certificate authority I chose. Right: Any trust anchor can vouch for any name, so your exposure is to the least careful anchor in the visitor’s store, in August 2026 one of roughly 121 roots in Mozilla’s server-authentication set, not the one you paid.
Wrong: Root certificates come from a central internet authority. Right: No such authority exists; four private root programmes run by Mozilla, Microsoft, Apple and Google each decide what is in their own store, coordinate disclosures through the Common CA Database, and may remove an anchor at their discretion, as Mozilla’s policy section 7.3 says in those words.
Wrong: HPKP was removed because pinning turned out to be a bad idea. Right: Pinning is sound and still used in browser-compiled static lists and in mobile applications; HPKP failed because it put an unrecoverable, attacker-settable, cache-persistent instruction in a header, so a lost key or a one-hour compromise could take a site offline for its whole max-age.
Wrong: A valid certificate proves the site belongs to the company you have in mind. Right: It proves somebody demonstrated control of that exact name to a certificate authority, which is why a phishing domain one letter from your bank obtains an equally valid certificate in minutes; chapter 28 sets out what an authority does and does not check.
Wrong: RFC 7469 has been withdrawn, so HPKP is formally dead. Right: As of August 2026 the IETF datatracker still lists it as a Proposed Standard from April 2015, with no obsoleting document and no reclassification to Historic, a useful reminder that standards status and deployment reality are different things.
25.99 Chapter summary in 20 lines#
- Public key cryptography proves facts about the holder of a key and can never by itself prove that the key belongs to a particular name.
- That gap is the introduction problem, and Diffie and Hellman named it in 1976 when they warned that the public directory of keys must be protected from modification.
- A binding between a name and a key must reach the verifier over an authentic channel, one where modification can be detected, though it need not be confidential.
- You can build a confidential channel out of an authentic one, as TLS does, and not the reverse, which is why trust anchors arrive with your operating system.
- A man in the middle needs no cryptographic weakness; she generates two key pairs, hands one to each victim, and relays between two genuine sessions.
- The Rivest and Shamir interlock protocol of 1984 can expose such a relay, but detection is not authentication and never tells you whose key you hold.
- Trust on first use records a key the first time and warns if it changes, converting a permanent attack into a one-shot attack at the start of the relationship.
- SSH is the canonical deployment, with known_hosts as the database, SHA-256 fingerprints since OpenSSH 6.8 of 18 March 2015, and accept-new since 7.6 of 3 October 2017.
- Setting StrictHostKeyChecking to no, as much automation does, disables the mechanism entirely and leaves encryption to an unidentified party.
- The web of trust arrived in PGP 2.0 after Zimmermann released PGP 1.0 in June 1991, and RFC 4880 section 5.2.1 defines its four certification types 0x10 to 0x13.
- OpenPGP separates validity, computed from signatures, from owner trust, assigned privately, and GnuPG needs one fully trusted or three marginal signers within five steps.
- It did not scale because paths do not exist between strangers, because its strong set peaked near 62,000 keys, and because the key server network collapsed in June 2019.
- A hierarchy pre-installs a few trust anchors on every device, so each new party needs one act of vouching rather than a path to everyone else.
- The price is that any anchor can vouch for any name, so your exposure is to the weakest member of the set rather than the authority you selected.
- Mozilla’s server-authentication root set held 121 certificates on 13 August 2026, down from 148 in November 2025, as the 15-year limit in policy section 7.4 takes effect.
- Four root programmes decide what is trusted, and as of August 2026 Mozilla’s policy is version 3.1 of 1 July 2026 and Chrome’s is version 1.8 of 5 February 2026.
- Six incidents between 2011 and 2015, including the DigiNotar compromise that ended in bankruptcy on 20 September 2011, showed the usual failure is authorized issuance, not theft.
- HPKP, published as RFC 7469 in April 2015, let a site pin the SHA-256 hash of its own public key information and required a backup pin in section 4.3.
- It was removed from Chrome and Firefox in version 72 of each, because a lost key or a brief compromise could make a site unreachable for its whole cached lifetime.
- Prevention by pinning gave way to detection through Certificate Transparency, restriction through CAA records, and pinning inside applications that ship with their servers.
Chapter sources: Diffie and Hellman, “New Directions in Cryptography”, IEEE Transactions on Information Theory, November 1976, section III; Kohnfelder’s MIT bachelor’s thesis, 1978, for the term certificate; Rivest and Shamir, “How to Expose an Eavesdropper”, Communications of the ACM volume 27 number 4, 1984; Zimmermann’s PGP 1.0 of June 1991 and his account of the trust model in chapter 7 of Beautiful Security, O’Reilly, 2009; the United States Attorney for the Northern District of California closing the Zimmermann investigation, 12 January 1996; RFC 4880, November 2007, sections 5.2.1, 5.2.3.13 and 5.2.3.14, and RFC 9580 of 2024 which obsoletes it with RFC 5581 and RFC 6637; the GnuPG manual for completes-needed, marginals-needed and max-cert-depth; RFC 4251, January 2006, section 4.1, and RFC 4255 for SSHFP; the OpenSSH release notes for 6.8 of 18 March 2015 and 7.6 of 3 October 2017, the ssh_config manual page, and client strings from OpenSSH 9.6p1; Robert J. Hansen, “SKS Keyserver Network Under Attack”, June 2019; Henk Penning’s strong set analysis and Wolf and Ortega-Arjona, September 2022; Dechand, Schuermann, Busse, Acar, Fahl and Smith, “An Empirical Study of Textual Key-Fingerprint Representations”, 25th USENIX Security Symposium, 2016; Mozilla Root Store Policy version 3.1, effective 1 July 2026, sections 3.1, 7.3, 7.4 and 7.5; Microsoft Trusted Root Program requirements as revised 28 April 2026, requirements 1, 5 and 11 and appendix items A.2 to A.4; Chrome Root Program Policy version 1.8 of 5 February 2026, section 1.2.1, and the Chromium announcement of the Chrome Root Store with Chrome 105 on 30 August 2022; Android Open Source Project documentation on the Conscrypt module and the network security configuration; Mozilla security blog posts of 25 March 2011 on Comodo and 23 March 2015 on the CNNIC intermediate; the Fox-IT Operation Black Tulip report on DigiNotar; CERT vulnerability note VU#529496 of 19 February 2015; the Google Online Security Blog of December 2013 on certificates chaining to ANSSI; RFC 7469 of April 2015, sections 2.1, 4.1, 4.3, 4.5 and appendices A and B, with its status checked on the IETF datatracker in August 2026; Scott Helme, “I’m giving up on HPKP”, 24 August 2017; the Chrome 72 deprecations and removals note; the Mozilla intent to unship dynamic HPKP for Firefox 72; RFC 9163 of February 2022 and the Chromium intent to remove Expect-CT at milestone 107; RFC 8659 for CAA and RFC 6698 for DANE; and the curl project’s record of certificate counts in its Mozilla-derived bundle for 4 November 2025, 19 March 2026, 16 July 2026 and 13 August 2026.