X3DH, Explained: The Handshake Behind Asynchronous Encryption
Every secure conversation starts with a problem that sounds impossible: two people need to agree on a secret key that nobody else can compute — but they are never online at the same time. You open a messenger, type a sentence to someone who is asleep on the other side of the planet, and hit send. For that message to be end-to-end encrypted, your phone has to derive a shared encryption key right now, with the recipient nowhere in sight. Classic key exchange can’t do this. The whole point of Diffie-Hellman is that both parties contribute a fresh secret in real time; if one of them is offline, there is no handshake to complete. The protocol that quietly solves this — and that sits underneath Signal, WhatsApp, and RVNT — is called X3DH, and understanding it is the clearest window into how modern asynchronous encryption actually works.
The asynchronous problem, stated plainly
X3DH (Extended Triple Diffie-Hellman) is a key-agreement protocol that lets two parties establish a shared secret even when only one of them is online, by having the offline party publish a set of public keys in advance. It was designed by Moxie Marlinspike and Trevor Perrin for the Signal Protocol and is specified in The X3DH Key Agreement Protocol (Revision 1, 2016).
The trick is to flip the timing. Instead of demanding that both parties be present, X3DH lets the recipient — call her Bob — pre-compute and publish a bundle of public keys ahead of time. The initiator — Alice — fetches that bundle, does some math against it on her own, derives a shared secret, and sends her first message immediately. Bob reconstructs the identical secret whenever he next comes online. No live round trip. No waiting.
The published material is called a prekey bundle, and it contains three kinds of keys:
- An identity key (IK) — Bob’s long-term public key, the thing that is Bob cryptographically.
- A signed prekey (SPK) — a medium-term key that Bob rotates periodically, signed by his identity key so Alice knows it’s genuine.
- A batch of one-time prekeys (OPK) — single-use keys, each handed out to exactly one initiator and then deleted.
In a server-based system the bundle lives on a key-distribution server. In a serverless one like RVNT, the bundle is fetched peer-to-peer or relayed, but the cryptography is identical: the server (or relay) never sees a private key and can’t read anything. It’s an untrusted dead-drop, not a trusted middleman.
Why “Triple” — and where the fourth comes from
The “Triple” in Triple Diffie-Hellman refers to the minimum three Diffie-Hellman computations the protocol performs. When a one-time prekey is available — the normal case — it does a fourth. Each DH operation mixes a different pair of keys, and the genius of the design is that each pair buys a different security property:
DH1 = DH(IK_A, SPK_B) Alice's identity key ↔ Bob's signed prekey
DH2 = DH(EK_A, IK_B) Alice's ephemeral key ↔ Bob's identity key
DH3 = DH(EK_A, SPK_B) Alice's ephemeral key ↔ Bob's signed prekey
DH4 = DH(EK_A, OPK_B) Alice's ephemeral key ↔ Bob's one-time prekey
The Signal spec is precise about the division of labor: “DH1 and DH2 provide mutual authentication, while DH3 and DH4 provide forward secrecy.” Let’s unpack what that actually means.
DH1 and DH2 — authentication. Both operations pull in a long-term identity key (Bob’s in DH1 via his signed prekey chain, and explicitly in DH2). Because Alice’s identity key feeds DH1 and Bob’s feeds DH2, the only way to compute the final secret is to hold those identity private keys. An impostor who doesn’t possess Alice’s identity key simply cannot produce a session that Bob will accept as coming from Alice. This is implicit mutual authentication — neither side gets an explicit “proof” until the first reply decrypts correctly, which is why verifying safety numbers out of band still matters.
DH3 and DH4 — forward secrecy. These operations lean on Alice’s ephemeral key (EK) — a keypair she generates fresh for this one handshake and deletes the instant X3DH finishes. Because the ephemeral private key is gone, an attacker who later steals Alice’s or Bob’s long-term identity key still can’t recompute the session secret. The disposable key required to do so no longer exists anywhere. (See our forward-secrecy deep dive for why “delete the key” is the whole game.)
DH4 specifically — replay protection. The one-time prekey is the unsung hero here. Each OPK is consumed and deleted the first time Bob processes an initial message that uses it. If an attacker captures Alice’s first message and replays it later trying to spin up a duplicate session, Bob’s OPK is already gone — the math can’t complete, and the replay is dead on arrival. When the OPK pool is exhausted and X3DH falls back to three DH operations, replay protection instead relies on the Double Ratchet advancing past the replayed message.
Compromising any single private key isn’t enough. To recover the session key, an attacker has to break every DH operation that fed it. That’s the structural strength of stacking four independent agreements.
Combining the secrets
The four DH outputs aren’t used as keys directly. They’re concatenated and run through a key derivation function — HKDF, built on HMAC-SHA256 — which extracts and expands the messy concatenation into a single uniform 32-byte session key:
SK = HKDF(DH1 || DH2 || DH3 || DH4)
This step matters more than it looks. HKDF guarantees that the output is indistinguishable from random as long as at least one input has enough entropy, and it cleanly “binds” the four secrets together so you can’t substitute one without changing the result. The KDF is the cryptographic glue that turns four separate guarantees into one inseparable key.
Alongside the session key, X3DH gives RVNT another property worth naming: offline deniability. Because either party could have constructed the transcript on their own, no third party can later prove that Alice authored a specific message. The handshake authenticates the conversation to its participants without producing a signature the world can wave around in court.
Seeding the Double Ratchet
X3DH does exactly one job, then bows out. It produces the initial shared secret — and that secret becomes the seed (the root key) for the Double Ratchet, the algorithm that takes over for the rest of the conversation.
This handoff is the architectural seam of the whole protocol. X3DH is a one-shot handshake; it runs once, establishes trust and a starting secret, and is never used again for that conversation. The Double Ratchet then evolves a fresh key for every single message, ratcheting forward so that compromising today’s key reveals neither yesterday’s messages nor tomorrow’s. X3DH gives you a secure front door; the Double Ratchet rebuilds the lock after every person who walks through. Together they deliver per-message forward secrecy and break-in recovery — but neither would function without the other.
Concretely, Alice’s first message carries everything Bob needs to catch up: her identity public key, her ephemeral public key, the ID of the one-time prekey she consumed, and the ciphertext. Bob looks up and deletes that OPK, runs the same four DH operations from his side, derives the identical session key, decrypts, and initializes his own Double Ratchet state. From that point the two ratchets march in lockstep. Full wire formats live in the RVNT key-exchange docs.
The quantum problem X3DH doesn’t solve
Here’s the uncomfortable truth about all of the above: every DH operation rests on the elliptic-curve discrete-log problem, and a sufficiently large quantum computer running Shor’s algorithm solves that problem in polynomial time. X25519 — the curve underneath classic X3DH — would fall. The session key would fall with it.
That’s not a 2040 concern; it’s a today concern, because of harvest-now, decrypt-later. A well-funded adversary can record your encrypted traffic and prekey bundles now, sit on the ciphertext for a decade, and decrypt everything retroactively the moment a cryptographically relevant quantum computer exists. If what you’re saying today will still be sensitive in fifteen years, classic X3DH alone is not enough.
The fix is to add a key-encapsulation mechanism whose security rests on lattice problems, which Shor’s algorithm does not break. Signal shipped this as PQXDH — the PQXDH Key Agreement Protocol by Ehren Kret and Rolfe Schmidt — which keeps the same DH operations and folds in an extra KEM shared secret:
SK = KDF(DH1 || DH2 || DH3 || DH4 || SS)
where SS is the secret produced by encapsulating against a post-quantum public key added to the prekey bundle.
RVNT’s hybrid: X25519 + ML-KEM-768
RVNT takes the same hybrid path with a deliberately conservative parameter choice. It pairs classical X25519 with ML-KEM-768, the lattice-based KEM standardized by NIST in August 2024 as FIPS 203: Module-Lattice-Based Key-Encapsulation Mechanism Standard (the algorithm formerly tracked as CRYSTALS-Kyber). The session-key derivation becomes:
(PQ_CT, PQ_SS) = ML-KEM-768.Encapsulate(Bob's PQ public key)
SK = HKDF(DH1 || DH2 || DH3 || DH4 || PQ_SS)
The word that matters is hybrid. ML-KEM does not replace the four DH operations — it’s concatenated alongside them before the KDF. That ordering is the entire safety argument:
| If… | …then the session is protected by |
|---|---|
| Quantum computers arrive and break X25519 | ML-KEM-768 (lattice-hard) |
| A classical attack breaks ML-KEM | All four X25519 DH operations |
| Both somehow break at once | Nothing — but so does the rest of the internet |
Because the combined secret is at least as strong as its strongest component (a property formally analyzed in the literature on KEM combiners), an attacker has to defeat both families of cryptography to recover the key. ML-KEM is newly deployed; X25519 has a decade of audited use behind it. Running them together means a flaw in either one is survivable.
A small but honest note on the parameter choice: Signal’s PQXDH recommends Kyber/ML-KEM at the highest level (Level 5), while RVNT uses ML-KEM-768 at NIST Level 3 — roughly AES-192-equivalent strength. That’s a defensible middle ground (smaller bundles and ciphertexts), and the design can be parameter-upgraded if the threat landscape demands it. The cost of the post-quantum layer is about 1.1 KB of extra data on the first message of a conversation and a fraction of a millisecond of compute. After the handshake, ML-KEM is never touched again — the Double Ratchet runs on AES-256-GCM and X25519 alone.
What the handshake does and doesn’t buy you
X3DH is a remarkably tight piece of engineering: four (or three) Diffie-Hellman operations, one KDF, and the asynchronous-messaging problem dissolves. You get mutual authentication, forward secrecy, replay protection, and offline deniability from a handshake the recipient never has to be awake for — and, in RVNT’s hybrid form, protection against an adversary recording your traffic today to crack it on a quantum computer tomorrow.
It’s worth being equally clear about the edges. X3DH establishes a confidential channel; it does nothing to hide who is talking to whom. That’s a separate concern handled by sealed sender, onion routing over Tor, and a mixnet — the metadata-privacy layers that sit above the crypto. And the authentication X3DH provides is implicit: it proves the other party holds the right identity key, but a determined attacker who can substitute a prekey bundle is why out-of-band safety-number verification still exists. RVNT is pre-release and has not yet been independently audited, so none of this should be taken as a finished security guarantee — it’s an honest description of the design, not a certification of it.
The handshake is just the opening move. But it’s the move that makes everything after it — the per-message ratcheting, the break-in recovery, the years-long resistance to quantum harvesting — even possible. Get the first key right, asynchronously, and the rest of the conversation has somewhere safe to stand.
Keep reading
All posts →-
Cryptographic Deniability: Why an Encrypted Message Can't Be Proven in Court
How cryptographic deniability lets an encrypted chat authenticate its participants yet prove nothing to a third party — the OTR origin, Signal's offline deniability, and the legal caveat.
9 min read -
Panic Mode and Remote Wipe: Surviving Device Seizure
How cryptographic self-destruct destroys keys to make ciphertext noise instantly, why crypto-erase beats file deletion, the Cellebrite/GrayKey threat, and honest limits.
9 min read -
Prekey Bundles: How Encrypted Chat Works When You're Offline
How prekey bundles let encrypted chat work when the recipient is offline: what they contain, how a sender derives a shared secret alone, and the key-substitution risk.
9 min read -
What Is a Duress PIN? How a Decoy Unlock Protects You Under Coercion
A duress PIN unlocks a believable decoy vault instead of your real data when you're forced to open your device. How it works, how it differs from a panic wipe, and where it fails.
9 min read -
What Is a Mixnet? Mix Networks vs Tor for Metadata Privacy
A mixnet batches, reorders, and delays encrypted traffic with cover noise to defeat timing analysis. How mix networks differ from Tor, and how RVNT layers both.
9 min read -
The Anthropic Recall: How Centralized AI Threatens Decentralized Privacy
A breakdown of today's US government export control directive targeting Anthropic, the vulnerabilities of centralized AI architectures, and why decentralized, sovereign communications are vital.
5 min read -
Sealed Sender: Hiding Who Talks to Whom
A technical deep-dive on RVNT's sealed sender: how encrypting the sender certificate to the recipient hides the from-to routing pair, and how forgery, replay, and abuse are handled.
9 min read -
Chat Control, Explained: The EU's Fight Over Scanning Your Messages
EU Chat Control explained: what the CSA Regulation proposes, why client-side scanning breaks end-to-end encryption, the 2025-2026 timeline, and its current status.
11 min read