Prekey Bundles: How Encrypted Chat Works When You're Offline
You open a messaging app, type “hey, you up?” to someone whose phone is dark on a nightstand three time zones away, and hit send. The message is end-to-end encrypted before it leaves your device. But encryption requires a shared secret key, and a shared secret normally takes two live participants negotiating it together. Your contact is asleep. There is no one on the other end to negotiate with. So how did your app produce a key that only the two of you can ever reconstruct — without either of you being online at the same time?
The answer is a small, unglamorous data structure called a prekey bundle: a packet of public keys your contact published in advance so that anyone can start an encrypted conversation with them later, alone, without their participation. It is the piece of plumbing that makes secure messaging feel like email instead of a phone call. Understanding it explains a lot about why modern encrypted chat is both remarkably private and quietly dependent on one verification step most people skip.
The asynchronous problem
Classic Diffie-Hellman key exchange — the textbook way two parties agree on a secret over an open channel — assumes both parties are online. Each side generates a fresh ephemeral keypair, sends the other its public half, and combines its own private key with the peer’s public key to arrive at the same shared value. It is elegant and it works, but it is fundamentally a handshake: a back-and-forth that needs both hands present at the same moment.
Real conversations are asynchronous. People are asleep, on planes, out of signal, or simply ignoring you. A protocol that requires a live handshake can’t deliver the first message until both devices happen to be awake together.
The pre-2010 workaround was ugly: queue an encryption request, wait for the recipient to come online, run the handshake, then finally send the message. That is slow, leaks the fact that you’re trying to reach someone, and falls apart the instant either party has flaky connectivity. The breakthrough — formalized by Trevor Perrin and Moxie Marlinspike in the Extended Triple Diffie-Hellman (X3DH) specification — was to let one party do their half of the handshake ahead of time and leave the results sitting on a server for whoever wants them. That cached half-handshake is the prekey bundle.
What’s actually in a prekey bundle
When your contact first set up the app, their device generated several keypairs and uploaded only the public halves. A prekey bundle, as defined in the X3DH spec, contains:
- The identity key (IK) — a long-lived public key that is the cryptographic identity of that account. It rarely or never changes. In RVNT this is an Ed25519 key claimed by proof of work rather than tied to a phone number or email.
- A signed prekey (SPK) — a medium-lived key the account rotates periodically (days to weeks). Crucially, it ships with a signature from the identity key over the prekey, proving the same account that owns the identity also authorized this prekey.
- A batch of one-time prekeys (OPKs) — single-use public keys, of which the server hands out exactly one per requester and then deletes it.
The signature is the load-bearing detail. When you fetch a bundle, the first thing your client does is verify the signed prekey against the identity key. The X3DH spec is explicit: “Alice verifies the prekey signature and aborts the protocol if verification fails.” That check ensures the prekey wasn’t swapped out by whoever stored the bundle — a point we’ll return to, because it has a sharp edge.
| Key in the bundle | Lifetime | Job |
|---|---|---|
| Identity key (IK) | Permanent | Authenticates the account; anchors trust |
| Signed prekey (SPK) | Medium-term, rotated | Provides authentication + forward secrecy; signed by IK |
| One-time prekey (OPK) | Single use, consumed | Adds forward secrecy and replay protection |
Deriving a shared secret, alone
Here is the part that feels like sleight of hand. With the bundle in hand, you generate one ephemeral keypair of your own and then perform a series of Diffie-Hellman operations — combining your private keys with their public keys — to compute a shared secret. Your contact, when they eventually wake up and receive your first message, runs the mirror-image computation with their private keys and your public ephemeral key, and lands on the identical secret. Neither of you was online with the other; the math simply meets in the middle.
X3DH does this not once but with several DH operations layered together. RVNT’s hybrid key exchange performs four:
DH1 = DH(IK_A, SPK_B) identity ↔ signed prekey → mutual authentication
DH2 = DH(EK_A, IK_B) ephemeral ↔ identity → forward secrecy
DH3 = DH(EK_A, SPK_B) ephemeral ↔ signed prekey → forward secrecy
DH4 = DH(EK_A, OPK_B) ephemeral ↔ one-time prekey → replay protection
Each line buys a distinct security property. DH1 binds both identity keys, so an attacker who doesn’t hold a private identity key can’t produce the secret — that’s the mutual authentication. DH2 and DH3 fold in your single-use ephemeral key, so even if a long-term key is stolen later, this session’s secret is unrecoverable, because the ephemeral private key was deleted right after use. DH4 consumes a one-time prekey, which the server deletes on handout, so an attacker can’t replay your opening message to spin up a duplicate session.
All of these outputs are concatenated and run through HKDF to produce a single root secret. An attacker has to compromise every relevant private key to reconstruct it; any one key alone is useless. That root secret then seeds the Double Ratchet, which takes over and gives every subsequent message its own forward-secret key — the subject of a separate deep dive.
There’s a quantum wrinkle worth naming. Plain DH is breakable by a future quantum computer running Shor’s algorithm, which threatens harvest-now-decrypt-later attacks — recording today’s ciphertext to crack a decade from now. RVNT therefore adds a fifth agreement: an ML-KEM-768 encapsulation, the lattice-based KEM standardized in FIPS 203 (published August 13, 2024). Its shared secret is concatenated alongside the four DH outputs before hashing, so the session stays secure as long as either the classical or the post-quantum half holds.
The server’s deliberately narrow job
Notice what the server did in all of this: it stored some public keys and handed one bundle to whoever asked. That’s it. It never saw a private key, never participated in deriving the secret, and cannot decrypt anything that follows. In RVNT there is no content server at all — the app is fully peer-to-peer — but even in a server-mediated design like Signal’s, the server’s role in key exchange is intentionally minimal. As the X3DH spec puts it, once both parties authenticate each other, “the only additional attack available to the server is to refuse to hand out one-time prekeys.”
That phrase — the only additional attack — is doing a lot of work, and it conceals the one real danger.
The server has to vouch for which identity key belongs to which account, because it’s the one serving you the bundle. If the server is honest, fine. If the server is compromised, coerced, or simply lying, it can hand you a bundle containing an identity key it controls instead of your contact’s. You’d derive a perfectly valid shared secret — with the attacker. The attacker decrypts your message, re-encrypts it under your contact’s real key, and forwards it along. Classic machine-in-the-middle, and the prekey signature check does not save you here: the malicious bundle is internally consistent because the attacker signed their own fake prekey with their own fake identity key. Everything verifies. It just verifies against the wrong person.
Verification is the step that closes the hole
This is exactly the gap that key verification exists to close, and it’s why every serious encrypted messenger offers some form of safety number or fingerprint comparison. The principle is simple: each conversation has a value derived from both parties’ real identity keys. If you and your contact compare that value through a channel the server doesn’t control — reading it aloud on a phone call, scanning a QR code in person, posting it somewhere the attacker can’t forge — and the values match, you’ve proven that no substituted key sits between you. The X3DH spec recommends precisely this: “Before or after an X3DH key agreement, the parties may compare their identity public keys through some authenticated channel.”
The cryptography guarantees you have a secure channel to someone. Verification is how you confirm that someone is who you think it is. Skip it and a key-substitution attack is undetectable.
RVNT exposes this as a verification step you can walk through with a contact (how to verify), and because it has no central content server, the trust surface is already smaller than in a server-mediated system. But smaller is not zero, and RVNT does not pretend otherwise: if you never verify, a hostile relay or a spoofed bundle source could in principle insert itself, exactly as with any other protocol in this family. Verification remains the human step the math cannot do for you.
What this does and doesn’t protect
It’s worth being precise about the boundary. Prekey bundles and X3DH protect the contents of your conversation and provide forward secrecy and post-quantum hedging for the key exchange. They do not, on their own, hide that you’re talking to someone, when, or how often — that’s metadata, and it leaks through the act of fetching a bundle in the first place. RVNT layers sealed sender, Tor routing, and a mixnet on top to attack that surface, but those are separate mechanisms from the key exchange described here.
And the honest caveats apply throughout: RVNT is pre-release software and has not been independently audited. The design follows well-studied constructions — X3DH, the Double Ratchet, FIPS-standardized post-quantum KEMs — but “follows good designs” and “has been proven correct in practice by outside experts” are different claims, and only the first one is true today.
What the prekey bundle gets right is the quiet miracle most people never think about: the ability to start a genuinely private conversation with someone who isn’t there. A few public keys, published in advance, let a stranger’s first message arrive already encrypted to a recipient who was asleep when it was composed. The only thing the math can’t supply is the last mile of trust — and that, deliberately, it hands back to you.
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 -
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 -
X3DH, Explained: The Handshake Behind Asynchronous Encryption
How X3DH lets two people share an encryption key when one is offline — the four Diffie-Hellman operations, what each provides, and the post-quantum upgrade.
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