In development. RVNT is pre-release — not yet security-audited. Source code, public builds, and the iOS / App Store release aren’t available yet. See the roadmap →

Protocols & Handshakes

Prekey Bundle

Also known as: prekey bundle, prekeys, key bundle, one-time prekey, signed prekey

A prekey bundle is a small package of a user's public keys, published to a server in advance, that lets anyone start an encrypted conversation with them while they are offline. It typically holds a long-term identity key, a signed medium-term prekey, and a batch of single-use one-time prekeys that the sender combines to derive a shared secret.

A prekey bundle is the thing that makes asynchronous encryption possible. Without it, the X3DH handshake would require both people to be online at the same instant. Instead, each user generates a stash of keys ahead of time and uploads only the public halves to a server. Anyone who wants to message them downloads one bundle and derives a shared secret entirely on their own; the recipient reconstructs the same secret whenever they next open the app.

A bundle contains three kinds of keys:

Identity key — long-lived, ties the bundle to the account (in RVNT, an Ed25519 key).

Signed prekey — rotated periodically (Signal rotates roughly every two days to a week) and signed by the identity key so a recipient can prove it is authentic.

One-time prekeys — a batch of single-use keys. The server hands out exactly one per new conversation and then deletes it, which is what gives the first message its replay protection and an extra forward-secrecy guarantee.

The server stores public keys only. It never sees a private key, never derives the shared secret, and cannot read messages. Its single risk is key substitution — handing out a bogus bundle — which out-of-band verification is designed to catch.

How it works

Setup (recipient, done once and refreshed periodically): generate an identity keypair, a signed prekey signed by the identity key, and N one-time prekeys. Upload the public keys.

Initiation (sender): request a bundle. The server returns the identity key, the current signed prekey, and pops one one-time prekey off the stack (deleting it). The sender verifies the signed prekey's signature, runs the X3DH DH operations against the bundle, and derives the session secret.

Depletion: one-time prekeys are consumed one per conversation. When the stash runs low the client uploads more. If it hits zero, new conversations proceed with the signed prekey alone until replenished.

How RVNT uses Prekey Bundle

RVNT's bootstrap/identity server holds only public prekey bundles plus DHT peer-discovery records — never keys, contacts, or content. RVNT bundles also carry a ML-KEM-768 public key (1184 bytes) so the hybrid post-quantum X3DH handshake has a lattice key to encapsulate against. See Key Exchange and the server doc for what the one server can and cannot see.

Frequently asked questions

Why are they called prekeys?

Because they are generated and published before any conversation begins, so a sender can use them without the recipient being present. The keys are staged in advance, ready for whoever reaches out first.

What happens when a user runs out of one-time prekeys?

New conversations fall back to using just the identity and signed prekeys, which still produces a secure session but loses the single-use replay protection the one-time prekey provided. Clients automatically upload a fresh batch when their stock runs low to avoid this.

Can the server read my messages if it stores my prekey bundle?

No. The bundle contains only public keys. The shared secret is derived on the devices, never on the server, and the server never holds any private key. Its only real risk is handing out a fake bundle, which safety-number verification is designed to detect.

Every definition here describes something RVNT actually ships — a post-quantum, end-to-end-encrypted, peer-to-peer messenger with no phone number and no servers.