How the @@ Protocol Works
A complete visual guide to the hardened split-body email architecture — from sending to decryption. All 6 critical weaknesses identified in the v0 security audit have been addressed (AES-256-GCM, envelope detachment, token hashing, rate limiting, PIN hardening, session key wallet).
flowchart TB
subgraph SEND["📤 SEND"]
A["1. Compose email to
user@@domain.com"]
B["2. Fetch recipient's
RSA-4096 public key"]
C["3. Build .eml file
(RFC 822: headers + body + attachments)"]
D["4. Compress with gzip level 9"]
E["5. Hybrid encryption:
AES-256-GCM (data) + RSA-4096 OAEP (AES key)
🔐 Authenticated encryption"]
F["6. ⚡ ENVELOPE detachment
eHead = encrypted AES key
eBody = nonce + tag + ciphertext"]
G["7. Store eBody on server
(SFTP external or local storage)
Referenced by hashed token"]
H["8. Generate download token
(256-bit, stored as SHA-256 hash)"]
I["9. Encrypt token with
recipient's public RSA key"]
J["10. Send regular email:
📎 eHead.bin attachment
🔑 Encrypted token in body"]
end
subgraph TRANSIT["📡 IN TRANSIT"]
K["eHead travels via SMTP
through mail servers"]
L["eBody NEVER travels
⬅ stays on server ⬅"]
end
subgraph RECEIVE["📥 RECEIVE"]
M["11. Recipient opens email
saves eHead attachment"]
N["12. Decrypts token with
private RSA key
🔑 Session key wallet (enter once)"]
O["13. Download page:
Token via POST/session
(no URL leak, hashed in DB)"]
P{"PIN required?"}
Q["Enter 6-digit PIN
🛡️ Progressive delay:
1s→2s→4s→8s→lockout"]
R{"2nd-channel (PWA)
enabled by sender?"}
S["📱 Authorize via PWA
on mobile phone"]
T["5-minute download window
🛡️ Rate-limited: 5 att/5min"]
U["14. Download eBody.bin"]
end
subgraph DECRYPT["🔓 FINAL DECRYPTION"]
V["15. Upload 2 files:
eHead.bin + eBody.bin
🔑 Key from session wallet"]
W["16. Parse envelope:
eHead → extract AES key
eBody → extract nonce+tag+ciphertext"]
X["17. Hybrid decrypt:
RSA-4096 decrypts AES key →
AES-256-GCM authenticates + decrypts"]
Y["18. Decompress (gzip)"]
Z["✅ Original .eml file
Openable in any email client"]
end
A --> B --> C --> D --> E --> F
F --> G
F --> H
G --> J
H --> I --> J
J --> K --> M
L -.-|"eBody never leaves the server"| U
M --> N --> O --> P
P -->|"Yes"| Q --> R
P -->|"No"| R
R -->|"Yes"| S --> T --> U
R -->|"No"| U
U --> V --> W --> X --> Y --> Z
style F fill:#ffc107,color:#333,stroke:#e0a800
style L fill:#dc3545,color:#fff,stroke:#c82333
style S fill:#ff6b6b,color:#fff,stroke:#e55a5a
style Z fill:#28a745,color:#fff,stroke:#1e7e34
| Parameter | Specification |
|---|---|
| Key Exchange & Asymmetric Encryption | RSA-4096 with OAEP padding (SHA-256). Public keys served via HTTPS (domain/PK/user) with database fallback. |
| Symmetric Encryption (Data) | AES-256-GCM with cryptographically random 256-bit key and 96-bit random nonce. Authenticated encryption (confidentiality + integrity in a single pass). |
| Message Authentication | GCM authentication tag (128-bit). Verified before any decryption — ciphertext tampering is detected and rejected. No padding oracle attack surface. |
| Compression | gzip level 9 (maximum) applied to .eml before encryption. Reduces payload size and increases entropy uniformity. |
| Download Token | 256-bit CSPRNG token, stored as SHA-256 hash in database. Plaintext token never persisted on server. Passed via POST/session — never in URL query strings. |
| PIN Protection | Optional 6-digit numeric PIN with progressive delay (exponential backoff: 1s→2s→4s→8s→16s). Combined with IP-based rate limiting (5 attempts/5 min, 15-min block). |
| Envelope Format | eHead = version(1B) + unique_id(16B) + encrypted_AES_key(512B). eBody = version(1B) + unique_id(16B) + nonce(12B) + GCM_tag(16B) + ciphertext. Version byte enables forward-compatible format evolution. |
1. Write the email
The sender composes a message addressed to user@@domain.com. The double @ indicates this will be an encrypted split-body email.
2. Fetch public key
The system looks up the recipient's RSA-4096 public key. First it tries the remote domain (https://domain/PK/user), then falls back to the local database.
3. Build .eml file
A standard RFC 822 .eml file is generated containing headers (From, To, Subject, Date), body, and any attachments in base64.
4. Compress
The .eml is compressed with gzip at maximum level (9) to reduce its size before encryption.
5. Hybrid encryption (AES-256-GCM + RSA-4096 OAEP)
A random AES-256 key encrypts the compressed data using AES-256-GCM (authenticated encryption). GCM provides both confidentiality and integrity without a separate HMAC. The AES key is then encrypted with the recipient's RSA-4096 public key (OAEP padding).
6. Envelope detachment
Instead of a blind binary split, the system creates a cryptographic envelope: eHead = version + unique_id + encrypted AES key, eBody = version + unique_id + nonce + GCM tag + ciphertext. Each part is useless without the other. This is the modern, secure approach to payload separation.
7. Store the eBody
The eBody is stored on the server (external SFTP storage or local disk). It is referenced by a SHA-256 hashed download token — not by plaintext identifiers. The eBody never travels through email — this is the core of the @@ protocol.
8. Generate download token
A cryptographically random 256-bit token is generated. The token is stored as a SHA-256 hash in the database — the plaintext token never persists on the server. This token is required to download the eBody.
9. Encrypt the token
The download token is encrypted with the recipient's RSA public key and displayed as a base64 string in the email body.
10. Send the email
A normal email is sent via SMTP (or Gmail API). The eHead file is attached as a .bin, and the encrypted token appears in the email body along with instructions.
11. Receive the email
The recipient receives a normal email with the eHead attached (.bin file) and an encrypted token in the body. They save the eHead file to their device.
12. Decrypt the token
At the Decrypt Token page, the recipient pastes the encrypted token and their private RSA key. The key can be stored in a session wallet ("Remember for this session") so it doesn't need to be re-entered on every page. The system decrypts the token, which is stored server-side in the session — never exposed in URLs.
13. Go to download page
The token is passed via POST/session (not URL query strings — preventing leaks in logs, proxies, and browser history). The token is SHA-256 hashed before any database lookup. Rate limiting allows 20 guesses per 5 minutes (15-minute block on excess).
14. Download the eBody
After passing PIN verification and/or PWA second-channel authorization (if required), the eBody file is downloaded. PIN attempts are protected by exponential backoff (1s → 2s → 4s → 8s → 16s delays) plus IP-based rate limiting (5 attempts per 5 minutes, 15-minute block). The download_action.php endpoint independently enforces second-channel authorization.
15. Upload 2 files (key from session wallet)
At the Decrypt page, the recipient uploads eHead.bin and eBody.bin. The private key is automatically loaded from the session wallet if unlocked — no need to upload the PEM file on every decryption. A "Lock Key" button clears the wallet.
16. Parse the cryptographic envelope
The system auto-detects protocol version (V1 GCM or legacy V0 CBC) and parses the envelope: eHead yields the encrypted AES key (with version and unique_id), eBody yields the nonce, GCM authentication tag, and ciphertext.
17. Hybrid decryption (AES-256-GCM)
The recipient's RSA-4096 private key decrypts the AES-256 key (OAEP unwrapping). Then AES-256-GCM verifies the authentication tag (integrity check) before decrypting — if the data was tampered with, decryption is rejected. No padding oracle vulnerabilities.
18. Decompress
gzdecode decompresses the decrypted data, yielding the original .eml file — readable in any email client (Thunderbird, Outlook, etc.).
1. Public Key Authenticity (MITM / Key Substitution)
The @@ protocol uses a TOFU (Trust On First Use) model: the first time a sender fetches a recipient's public key from the server, they trust it is authentic. A compromised server could theoretically serve a fake public key, enabling a man-in-the-middle attack.
Mitigations in place: (a) Public keys are served exclusively over HTTPS, protecting against network-level tampering. (b) The PWA second-channel verification (Task F) means an attacker who substituted the key still cannot download the eBody without the verification code delivered to the recipient's device.
Residual risk: A server operator or an attacker with server-level access could substitute keys. Users requiring high assurance should verify key fingerprints through an out-of-band channel (e.g., phone call, Signal message). A key fingerprint page is available at ?page=key-fingerprint&email=user@domain.com. Future versions may add Certificate Transparency-style key change logging and user-visible key change alerts (similar to Signal safety numbers).
2. Perfect Forward Secrecy (PFS)
The @@ protocol uses long-lived RSA-4096 key pairs. If a recipient's private key is compromised in the future, all historical messages encrypted to that key can be decrypted. This is an inherent property of RSA-based key exchange — the same limitation exists in classic PGP and S/MIME.
Why RSA was chosen: RSA-4096 key pairs can be generated by the user on their own machine and the public key can be served from any HTTPS endpoint. This enables self-hosted key directories without requiring the server to participate in key generation — a deliberate architectural choice to keep the server untrusted for key material.
Defense in depth: The PWA second-channel verification and optional PIN add layers of protection that are not dependent on the RSA key pair. Even with the private key, an attacker cannot download the eBody without the second factor.
Future roadmap: Adding ephemeral ECDH key exchange (X25519) alongside RSA for forward-secret sessions is under consideration for protocol v2.
3. Metadata Exposure
While the @@ protocol encrypts message content (body + attachments), it does not hide communication metadata: sender identity, recipient identity, timestamps, message frequency, and approximate message size remain visible through SMTP headers and server logs.
Why this is hard to fix: Email metadata is inherent to SMTP — mail servers need sender/recipient to route messages. Hiding metadata would require replacing SMTP itself, which is beyond the scope of @@ (which is designed to work WITH existing email infrastructure).
Mitigations: The eHead/eBody split means the server sees only encrypted blobs without content. Download logs are rate-limited and hashed. For users requiring metadata protection, the @@ protocol should be combined with a transport-layer solution like Tor.
4. JavaScript Delivery Trust (Web Crypto Problem)
Encryption and decryption happen in the browser using JavaScript served by the web server. A compromised or malicious server could serve modified JavaScript that exfiltrates plaintext or private keys before encryption.
This is a fundamental limitation of ALL browser-based cryptographic systems — including Proton Mail web client, Tutanota web client, and every other webmail encryption solution. There is no complete fix without moving to a native application with signed binaries.
Mitigations in place: (a) All encryption/decryption code is in publicly viewable JavaScript (not minified or obfuscated) — users can inspect the source. (b) The decryption page (decrypt.php) can be downloaded and run locally/offline. (c) Future versions will add Subresource Integrity (SRI) hashes on all script tags.
✅ Defended Against
- Passive network eavesdropping (HTTPS + AES-256-GCM)
- Active network attackers between sender and mail server (HTTPS)
- Server operator reading message content (client-side encryption, eHead/eBody split)
- Download token leakage via URL logs (POST/session, SHA-256 hashed in DB)
- Brute-force attacks on PIN or token (rate limiting + exponential backoff)
- Quantum computer deriving private key from public key (PWA 2nd channel + PIN)
⚠️ Not Defended Against (Residual Risk)
- Server-level key substitution / malicious server (TOFU model limitation)
- Communication metadata analysis (SMTP headers are in cleartext by design)
- Historical message decryption after future key compromise (no PFS with RSA)
- JavaScript supply-chain attacks (inherent to browser-based crypto)
- Endpoint compromise (malware, keyloggers, browser extensions)