Why I switched from RSA to X25519 for email encryption
While building an encrypted email service, I had to choose between RSA and X25519 (Curve25519) for key exchange. Here are real benchmarks from our Node.js implementation:
Key Generation
| Algorithm | Time | Key Size |
|---|---|---|
| X25519 | ~0.1ms | 32 bytes |
| RSA-2048 | ~50ms | 256 bytes |
| RSA-4096 | ~500ms | 512 bytes |
X25519 is 500-5000x faster for key generation.
Our ECIES Pattern
We use X25519 + HKDF + AES-256-GCM (ECIES pattern):
1. Generate ephemeral X25519 keypair
2. ECDH(ephemeral_priv, recipient_pub) → shared_secret
3. HKDF(shared_secret, info) → aes_key (32 bytes)
4. AES-256-GCM(aes_key, plaintext) → ciphertext + auth_tag
The envelope is a compact JSON:
{
"v": 1,
"alg": "X25519-HKDF-AES256GCM",
"epk": "<base64 ephemeral public key>",
"iv": "<12 bytes>",
"tag": "<16 bytes>",
"ct": "<ciphertext>"
}
Why not PGP?
PGP is the standard for email encryption but:
- Key management is painful for regular users
- No forward secrecy (same key for all messages)
- Large keys and slow operations
X25519 ECIES gives us ephemeral keys per message (forward secrecy) with minimal overhead.
Browser Implementation
Web Crypto API supports X25519 natively in modern browsers, so we can encrypt/decrypt client-side without any library:
const keyPair = await crypto.subtle.generateKey(
{ name: "X25519" },
true,
["deriveKey"]
);
Trade-offs
- Pro: Fast, small keys, forward secrecy, browser-native
- Con: Less widely adopted than RSA, no direct signing (use Ed25519 separately)
Would love to hear from others implementing email encryption. What patterns are you using?
Built with Node.js crypto module (server) + Web Crypto API (client)
Top comments (3)
The Web Crypto API benchmarks are compelling — that 500x key generation speedup is hard to argue against, especially for per-message ephemeral keys.
One practical consideration from building a local-first email client: most email encryption doesn't fail at the algorithm level, it fails at key management UX. PGP has had excellent algorithms for decades and under 1% adoption because managing keys is painful. Your ECIES approach with automatic ephemeral generation is an improvement, but recipients still need to decrypt, which brings you back to key exchange.
The forward secrecy argument is the strongest case for X25519 in email specifically. Traditional PGP gives you one static key pair, so a single key compromise exposes your entire history. Ephemeral keys per message mean compromising one doesn't help with others. That's a meaningful security upgrade for the email use case.
One caveat on the “forward secrecy” bit: X25519 with an ephemeral sender key and a long-term recipient public key is usually better thought of as ECIES-style sealed-box encryption, not full forward secrecy.
If the recipient’s long-term private key is compromised later, an attacker who saved old envelopes still has the ephemeral public key from each message and can recompute the shared secret for old mail. You only get the forward-secrecy property if the recipient side also rotates/deletes private key material in a ratchet/session scheme.
We’re building something in a similar neighborhood at privacy.fish — an email provider that encrypts stored mail with age, and focuses on sending/downloading mail over SSH so the mailbox can stay more local-first and less webmail-centric.
Still a nice direction for browser-native encrypted mail, especially compared with dragging RSA around. I’d just be careful about promising FS unless there’s recipient key rotation in the design.
thanks