Version 1.0 | February 2026
The Fourier Protocol
A modern end-to-end encryption protocol providing forward secrecy, post-compromise security, and scalable group encryption. Built on the Signal Protocol implementation with enhancements for metadata protection and large-scale groups.
Contents
1. Protocol Overview
The Fourier Protocol provides end-to-end encryption for all messaging in a.s.d.f. It ensures that the server operates as a "dumb relay" — storing and forwarding ciphertext without the ability to decrypt message content.
The protocol supports three chat types, each with a tailored encryption scheme:
| Chat Type | Encryption Scheme | E2EE | Max Size |
|---|---|---|---|
| Direct 1:1 | X3DH + Double Ratchet | Full E2EE | 2 users |
| Private Group | Sender Keys | Full E2EE | 1,000 members |
| Public Group | Epoch Keys | Server-managed | 200,000 members |
2. Architecture & Layers
Fourier is structured as three independent layers, each with a distinct responsibility:
Application Layer
Messages, Groups, Media, Presence, Reactions, Receipts
Encryption Layer
X3DH, Double Ratchet, Sender Keys, Epoch Keys
Transport Layer
HTTPS REST + WebSocket (TLS 1.3)
The encryption layer is implemented entirely on the client. The server only sees opaque ciphertext and routing metadata (user IDs, chat IDs, timestamps).
3. Cryptographic Primitives
Fourier uses well-studied, constant-time cryptographic primitives:
| Primitive | Algorithm | Key Size | Purpose |
|---|---|---|---|
| Digital Signature | Ed25519 | 256-bit | Identity authentication, prekey signing |
| Key Agreement | X25519 (ECDH) | 256-bit | Diffie-Hellman in X3DH and Double Ratchet |
| Symmetric Encryption | ChaCha20-Poly1305 | 256-bit | AEAD message encryption |
| Key Derivation | HKDF-SHA256 | Variable | Deriving root, chain, and message keys |
| Hashing | SHA-256 | 256-bit | Safety numbers, fingerprints |
All secret key material is zeroized from memory upon drop, preventing key recovery from process memory.
4. X3DH Key Agreement
X3DH (Extended Triple Diffie-Hellman) establishes a shared secret between two parties, even when one is offline. Fourier uses the 4-DH variant when a one-time prekey is available, falling back to 3-DH otherwise.
Key Types
| Key | Lifetime | Purpose |
|---|---|---|
| Identity Key (IK) | Device lifetime | Long-term Ed25519 identity |
| Signed Prekey (SPK) | 7–30 days | Medium-term X25519, signed by IK |
| One-Time Prekey (OPK) | Single use | Consumed during handshake |
| Ephemeral Key (EK) | Per session | Fresh randomness per handshake |
Handshake Flow
Alice Server Bob
| | |
| 1. Fetch Bob's PreKeyBundle | |
|------------------------------>| |
| { IK_B, SPK_B, OPK_B } | |
|<------------------------------| |
| | |
| 2. Verify SPK_B signature | |
| with IK_B | |
| | |
| 3. Generate Ephemeral Key | |
| EK_A = X25519_GENERATE() | |
| | |
| 4. Compute 4 DH secrets: | |
| DH1 = IK_A x SPK_B | |
| DH2 = EK_A x IK_B | |
| DH3 = EK_A x SPK_B | |
| DH4 = EK_A x OPK_B | |
| | |
| 5. Derive shared secret: | |
| HKDF(DH1||DH2||DH3||DH4) | |
| info: "Fourier X3DH v1" | |
| | |
| 6. Send initial message | |
| + EK_A public key | |
|------------------------------>|----------------------------->|
| | 7. Server deletes used OPK |
| | |
| | 8. Bob computes same |
| | 4 DH operations |
| | + derives secret |
X3DH handshake: Alice initiates an encrypted session with offline Bob
What Each DH Provides
| DH | Provides | Without It |
|---|---|---|
| DH1 | Mutual authentication | Server could impersonate Bob |
| DH2 | Alice proves identity | Messages could be forged |
| DH3 | Forward secrecy (medium-term) | Identity key compromise breaks all sessions |
| DH4 | One-time forward secrecy | Replay attacks on initial messages |
5. Double Ratchet
After X3DH establishes the initial shared secret, the Double Ratchet provides continuous forward secrecy and post-compromise security. It combines two ratchets:
Root Key (from X3DH)
|
| DH Ratchet Step (new key material)
v
+-----------+ +-----------+
| Root Key' |----+ | Root Key''|----+
+-----------+ | +-----------+ |
v v
+-----------+ +-----------+
| Chain Key | | Chain Key |
| (Send) | | (Receive) |
+-----------+ +-----------+
| |
Symmetric Ratchet Symmetric Ratchet
(per message) (per message)
| |
+-----+-----+ +-----+-----+
| | | | | |
v v v v v v
MK0 MK1 MK2 MK0 MK1 MK2
(msg keys, single use, deleted after decrypt)
Double Ratchet: DH ratchet advances on turn changes; symmetric ratchet advances per message
DH Ratchet
When the conversation turn changes (Alice receives a reply from Bob with a new ratchet public key), a DH ratchet step introduces fresh randomness:
- Compute DH:
dh_output = X25519(our_secret, their_new_public) - Derive new keys:
(new_root_key, new_chain_key) = HKDF(root_key, dh_output, "Fourier Double Ratchet v1") - Generate a new DH key pair for the next turn
Symmetric Ratchet
For each message within a chain:
- Derive:
(new_chain_key, message_key) = HKDF(chain_key, "Fourier Chain+Message Keys v1") - Encrypt with ChaCha20-Poly1305 using the message key
- Advance chain key, delete message key immediately
Out-of-order messages: Up to 1,000 skipped message keys are cached. Each cached key is single-use and deleted after decryption, preventing replay attacks.
Message Wire Format
+-------------------+-------------------------------------+ | Field | Size | +-------------------+-------------------------------------+ | version | u32 (currently 1) | | ratchet_key | 32 bytes (sender's DH public key) | | message_number | u64 (position in chain) | | prev_chain_length | u64 (previous chain length) | | ciphertext | variable (ChaCha20-Poly1305 + tag) | | associated_data | variable (authenticated metadata) | +-------------------+-------------------------------------+
Encrypted message format for 1:1 conversations
6. Sender Keys (Group E2EE)
Private groups (up to 1,000 members) use Sender Keys for efficient E2EE. Each member maintains their own sending key and encrypts once for the entire group — O(1) encryption instead of O(N) pairwise.
Alice (sender) Group Members
| |
| 1. Generate SenderKey: |
| { chain_key, signing_key, seed } |
| |
| 2. Distribute via 1:1 encrypted channels |
| (Double Ratchet to each member) |
| |
| Alice ---[DR]---> Bob: SenderKey |
| Alice ---[DR]---> Charlie: SenderKey |
| Alice ---[DR]---> Diana: SenderKey |
| |
| 3. Encrypt group message (O(1)): |
| mk = HKDF(chain_key, seed) |
| ct = ChaCha20(mk, plaintext) |
| sig = Ed25519.Sign(ct) |
| chain_key = HKDF(chain_key) // ratchet |
| |
| 4. Send single ciphertext |
|------------------>[ Server ]--------------------->|
| (opaque) |
| |
| 5. Each member decrypts: |
| Verify Ed25519 sig |
| Derive mk from chain |
| Decrypt with mk |
Sender Keys: O(1) encryption for private groups with per-sender chains
Key Rotation
Sender keys are regenerated and redistributed when:
- Member joins — backward secrecy: new members cannot decrypt prior messages
- Member leaves — forward secrecy: departed members cannot decrypt future messages
- Periodic rotation — limits exposure if a sender key is compromised
7. Epoch Keys (Public Groups)
For large public groups (up to 200,000 members), full E2EE with Sender Keys is impractical due to O(N²) key distribution. Fourier uses server-managed epoch keys for scalability.
K_master (per room, created once)
|
| HKDF("epoch||room_id||epoch_number")
v
K_epoch_0 ---> K_epoch_1 ---> K_epoch_2 ---> ...
| | |
| HKDF | HKDF | HKDF
v v v
msg_key_0 msg_key_0 msg_key_0
msg_key_1 msg_key_1 msg_key_1
msg_key_2 msg_key_2 msg_key_2
... ... ...
Epoch rotates on:
+-------------------+------------------------+
| Trigger | Security Property |
+-------------------+------------------------+
| Member joins | Backward secrecy |
| Member leaves | Forward secrecy |
| Hourly timer | Limits exposure window |
+-------------------+------------------------+
Epoch key hierarchy: per-epoch keys derived from a master key
Important: In public group mode, the server manages key material and can theoretically decrypt messages. Users are clearly informed that public groups do not provide the same E2EE guarantees as direct messages or private groups.
8. Security Properties
Threat Model
| Threat | Mitigation |
|---|---|
| Passive network observer | TLS 1.3 + E2EE double-layer encryption |
| Compromised server | Server only sees ciphertext; cannot derive plaintext |
| Man-in-the-middle | Signed prekeys + safety number verification |
| Past key compromise | Forward secrecy via ephemeral keys and chain ratcheting |
| Current key compromise | Post-compromise security via DH ratchet self-healing |
| Message replay | Monotonic counters, one-time skipped keys |
| Traffic analysis | Message padding (fixed-size tiers), auto-purge |
What the Server Knows vs. Doesn't Know
+-----------------------------+-------------+ | Data | Server Sees | +-----------------------------+-------------+ | User IDs, device IDs | Yes | | Who messages whom (chat ID) | Yes | | Message timestamps | Yes | | Message content (plaintext) | NO | <-- 1:1 & private groups | Encryption keys | NO | | Group membership | Yes | | Encrypted ciphertext | Yes(opaque)| +-----------------------------+-------------+
Safety Numbers
Users can verify each other's identity out-of-band using Safety Numbers — a 60-digit fingerprint derived from both parties' identity keys. If a user's identity key changes (new device, re-registration), the safety number changes and the app alerts the user.
9. Protocol Enhancements
Fourier extends the base Signal Protocol implementation with additional protections:
| Enhancement | Status | Description |
|---|---|---|
| Message Padding | Implemented | Fixed-size tiers (256B to 1MB) prevent length-based traffic analysis |
| Header Encryption | Implemented | Encrypts ratchet keys and counters to hide metadata |
| Message Compression | Implemented | zstd compression before encryption reduces bandwidth |
| Auto-Purge | Implemented | Messages deleted from server after all recipients confirm delivery |
| PQXDH | Planned | Post-quantum X3DH using Kyber-1024 hybrid key exchange |
| Sealed Sender | Planned | Hide sender identity from the server |
The full technical specification is available in the opacE2EE audit framework and the Noel Protocol Standard document. For security audit results, see our Security Audit page.