How do you implement end-to-end encryption over WebSockets?

Answer

wss:// provides transport-layer encryption (TLS) — data is encrypted between client and server, but the server can see message content. End-to-end encryption (E2EE) encrypts messages so only the intended recipient can decrypt them — not even the server. Implementation: (1) Key exchange — use the Web Crypto API's ECDH to perform Diffie-Hellman key exchange between clients (mediated by the server but without the server learning the shared secret); (2) Encryption — use AES-GCM (authenticated encryption) with the shared key to encrypt message payloads before sending; (3) Server as relay — the server only sees opaque encrypted blobs and routes them without being able to read content; (4) Key management — handle key storage (IndexedDB), key rotation, and multi-device sync. Libraries like libsodium-wrappers (JavaScript port of libsodium) simplify the cryptographic operations. Signal Protocol (used by WhatsApp, Signal) adds forward secrecy with double ratchet algorithm.