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 (1)
thanks