Relay
The End-to-End Layer: What the Relay Can Never See
7 min read
Before we can talk about hiding who sent a message, or when, or how often, we have to be sure of the easy-sounding part: that the relay cannot read the message at all. "Easy- sounding" is doing a lot of work in that sentence.
This is the foundation article of the series. Every later piece — sealed sender, unlinkability, the envelope, deniability — assumes that the body of a message is opaque to the relay. Here is how that opacity is built, why the obvious version of it is not enough, and where the one part we did not build ourselves begins.
1. What "end-to-end" actually promises
End-to-end encryption (E2EE) means the keys that can decrypt a message live only on the two end devices — Alice's phone and Bob's phone — and never on the server between them. The relay ferries ciphertext it cannot open. If that were the whole story, this article would be one paragraph.
It is not the whole story, for three reasons that each turned into real engineering:
- The two phones are never online together. Alice wants to message Bob while Bob's phone is asleep. You cannot run an interactive key exchange with someone who isn't there. So the session setup has to be asynchronous.
- Keys leak eventually. Phones get seized, backed up, malware'd. A good messenger assumes today's key will eventually be compromised and limits the blast radius: a stolen key must not unlock yesterday's messages, nor tomorrow's.
- "Encrypted" is not automatically "quantum-safe." The classic key exchange is Diffie–Hellman, which a quantum computer breaks — and a recorded conversation is a sitting duck for harvest-now-decrypt-later.
The messenger that solved (1) and (2) beautifully is Signal, and we use Signal's library, libsignal, for exactly this layer. Our job was to pick it, wire it correctly, insist on its post-quantum mode, and guard that insistence. Let us walk the three problems.
2. Talking to someone who isn't there: prekeys and PQXDH
To start a conversation with an offline Bob, Alice needs something of Bob's to encrypt to, right now, without Bob's participation. The mechanism is prekeys: when Bob first installs the app, his phone uploads a small stack of public keys to the server and goes to sleep. When Alice wants to message him, she downloads one of Bob's prekeys, does a key agreement against it, and sends. Bob catches up later. The server stores and hands out public keys only — it is a key vending machine, never a keyholder.
The mental model is a wall of lockboxes with fresh padlocks. Bob leaves a stack of open padlocks at the front desk. Anyone can grab one, lock a message in a box, and leave it; only Bob has the matching key. He was asleep the whole time.
The classic version of this dance is Signal's X3DH ("Extended Triple Diffie–Hellman"): it mixes several Diffie–Hellman operations between Alice's and Bob's keys so that the resulting shared secret depends on both long-term identity keys and fresh per-session keys. That last part matters — it is what gives the session its initial forward secrecy.
But every one of those operations is a Diffie–Hellman, and Diffie–Hellman is precisely what Shor's algorithm dismantles. So we use the post-quantum upgrade, PQXDH, which adds a lattice key-encapsulation (ML-KEM) alongside the classical exchanges. The session secret now depends on a problem believed hard for quantum computers and the battle-tested classical one — a hybrid, so a break of either alone is survivable. A recording of the setup no longer contains a Diffie–Hellman transcript a future machine can unwind. (Signal deployed PQXDH in 2023; the specification is a clean read.)
3. A fresh key for every message: the Double Ratchet
Session setup gives Alice and Bob one shared secret. If they used it directly for every message forever, a single key theft would decrypt the entire history and future of the conversation. That is unacceptable, so the shared secret is only a seed.
From that seed, the Double Ratchet derives a brand-new key for every single message and throws the old ones away. Two properties fall out, and they are the reason the ratchet is famous:
- Forward secrecy. Because each message's key is deleted right after use, an attacker who seizes Alice's phone today learns nothing about the messages she already sent — those keys are gone. The past is safe.
- Post-compromise security (self-healing). The ratchet periodically mixes in fresh Diffie–Hellman material as messages flow back and forth. So even if an attacker steals the current key, the next round injects randomness they never saw, and the conversation heals itself back to secrecy. The future recovers.
The picture is a hotel that re-keys your door lock after every single entry, and derives each new key partly from a coin flip it makes inside the room where no one is watching. Steal one key card and you get exactly one door opening, in the past, once.
The "double" is because two ratchets turn together: a symmetric one that clicks forward on every message (cheap), and a Diffie–Hellman one that clicks when the direction of conversation changes (the healing step). The full mechanism is one of the most elegant constructions in applied cryptography, and Signal documents it far better than we could re-derive here: The Double Ratchet Algorithm.
4. The subtle gap: a ratchet that heals classically
Here is the wrinkle that is easy to miss, and it is the reason this article exists rather than just pointing at Signal's docs.
PQXDH makes the setup post-quantum. But the Double Ratchet's self-healing step — the part that re-injects fresh secrecy as the conversation continues — is a Diffie–Hellman. That means a long conversation, over time, keeps folding in classical key material. An attacker who compromises a device and wants to be locked back out relies on that healing step; if the healing is Diffie–Hellman, a quantum adversary can follow along and never gets locked out. Post-quantum setup with a classical ratchet is a house with a quantum-proof front door and ordinary windows.
The fix is SPQR — the Sparse Post-Quantum Ratchet — which threads lattice key-encapsulation material through the ongoing ratchet, so the healing itself becomes quantum-safe. "Sparse" is the engineering compromise at its heart: running a full post-quantum KEM on every message would be bandwidth-prohibitive (lattice ciphertexts are kilobytes, not the 32 bytes of a curve point), so SPQR spreads the post-quantum refresh across messages, amortizing the cost while still guaranteeing the conversation heals post-quantum on a bounded schedule. It ships in libsignal (version 0.94.0 and up) and rides in a dedicated field of every steady-state message.
5. The part that is ours: trust, but verify the ratchet
We did not build PQXDH, the Double Ratchet, or SPQR. We chose them, and then we did the thing a security engineer must do with a dependency this load-bearing: we refused to take it on faith.
The risk is quiet failure. A misconfiguration, a downgraded library version, or a bug could leave the post-quantum ratchet field absent from a steady-state message — and everything would still work perfectly, still encrypt, still deliver, while silently having dropped back to classical-only security. A recording made during that window would be harvest-now-decrypt-later bait, and nobody would notice.
So we added a small, mean guard. On both the send and the receive path, before a steady-state message is allowed through, a tiny check walks the encrypted frame's structure and asserts that the post-quantum ratchet field is actually present. If it is missing, the message is rejected, fail-closed — we would rather drop a message than send one that lies about being quantum-safe. And a build-time floor pins the libsignal version at or above the release where SPQR is guaranteed, so a dependency downgrade fails the build rather than the users. It is a dozen lines of code standing guard over the most important assumption in the system.
This is the pattern for the whole series: where we consume someone else's excellent cryptography, we consume it and we build a fail-closed tripwire that screams if the guarantee ever silently lapses.
6. What this buys the rest of the series
From here on, every article gets to assume the message body is a sealed, post-quantum, forward-secret, self-healing blob that the relay cannot read and a future quantum computer cannot unwind from a recording. That is the floor.
But notice what it does not give us. Content encryption says nothing about who sent the blob, whether two blobs came from the same person, what kind of message it is, or whether the relay keeps a copy. Those are all metadata, all outside the seal, and all still fully visible to a naive relay. Peeling each of them away is the rest of the series, starting with the most basic: hiding the sender, in Sealed Sender.
References & further reading
- Signal, "The PQXDH Key Agreement Protocol" — post-quantum asynchronous session setup.
- Signal, "The X3DH Key Agreement Protocol" — the classical predecessor, worth reading first for the prekey idea.
- Signal, "The Double Ratchet Algorithm" — forward secrecy and post-compromise security.
- Signal, "The PQXDH and Sparse Post Quantum Ratchet" — the SPQR design and why the ratchet, not just the setup, must go post-quantum.
- NIST FIPS 203 (ML-KEM) — the lattice KEM inside PQXDH and SPQR.