react-e2ee
react-e2ee provides headless React hooks and low-level utilities for client-side end-to-end encryption using the browser's native Web Crypto API.
- Zero runtime dependencies — only React as a peer dependency
- Every cryptographic operation runs entirely in the browser
- No key ever leaves the client's device
- Fully typed with TypeScript
What it does
| Feature | Hook / API | Status |
|---|---|---|
| RSA-OAEP key pair lifecycle | useKeyPair | ✅ Available |
| RSA-OAEP encryption | useEncrypt | ✅ Available |
| RSA-OAEP decryption | useDecrypt | ✅ Available |
| AES-GCM symmetric key lifecycle | useSymmetricKey | ✅ Available |
| IndexedDB key storage by identifier | useKeyStorage | ✅ Available |
| Password → AES key (cross-device, PBKDF2) | useSeedKey | ✅ Available |
| Platform public key for emergency access | usePlatformAccess | ✅ Available |
| Cryptographic hashing (SHA family) | useDigest | ✅ Available |
| HMAC message authentication | useHmac | ✅ Available |
| ECDSA digital signatures | useSign | ✅ Available |
| Key fingerprinting | useFingerprint | ✅ Available |
| RSA key pair with server-stored encrypted private key | useServerKeyPair | ✅ Available |
How it works
Asymmetric (RSA-OAEP)
A key pair is generated in the browser. The public key can be safely shared — it is used to encrypt data. Only the holder of the private key can decrypt it. This is the classic E2E model used by chat apps and secure messaging protocols.
Sender Receiver
────── ────────
publicKey ─────────▶ encrypt(data)
│
▼
ciphertext ──▶ privateKey ─▶ decrypt ─▶ plaintext
Symmetric (AES-GCM)
A single key is used for both encryption and decryption. AES-GCM is faster and supports larger payloads than RSA. Commonly used in hybrid patterns: RSA encrypts the AES key, AES encrypts the data.
Cross-device (PBKDF2)
useSeedKey derives the same AES-GCM key from a password and identifier using PBKDF2. Because the derivation is deterministic, the exact same key is produced on any device given the same inputs — no key synchronization required.
Device A Device B
──────── ────────
password + identifier password + identifier
│ │
PBKDF2 PBKDF2
│ │
AES key ◀──────────────────▶ AES key (identical)
Requirements
| Requirement | Details |
|---|---|
| React | 18 or 19 (peer dependency) |
| Browser | Chrome 37+, Firefox 34+, Safari 11+, Edge 79+ |
| Secure context | HTTPS or localhost — SubtleCrypto is unavailable on plain HTTP |
| Node.js | ≥ 18 (library build tooling; SSR environments must polyfill Web Crypto) |
The Web Crypto API (SubtleCrypto) is only available in secure contexts. Your app must be served over HTTPS in production. During development, localhost is automatically treated as secure by the browser.
Algorithms
| Algorithm | Key size | Use case |
|---|---|---|
| RSA-OAEP | 2048-bit, SHA-256 | Asymmetric encryption of small payloads |
| AES-GCM | 256-bit, 96-bit IV | Symmetric encryption of any payload size |
| PBKDF2 | SHA-256, 600 000 iterations (OWASP 2024) | Key derivation from a password — used by useSeedKey |
| HMAC | SHA-256/384/512 | Keyed message authentication — used by useHmac |
| ECDSA | P-256 / P-384 / P-521 | Digital signatures — used by useSign |
| SHA-256/384/512 | N/A | Cryptographic hashing — used by useDigest, useFingerprint |
Emergency access
usePlatformAccess lets you attach an optional platform layer to any encrypted payload — without breaking normal end-to-end confidentiality. The platform holds an RSA key pair; its public key is embedded in the app config. Whenever a user encrypts data, the AES key is also RSA-wrapped for the platform and stored as a "platform envelope" next to the ciphertext. In an emergency, the platform decrypts the envelope with its private key to recover the AES key.
User encrypts
─────────────
aesKey ──▶ aesEncrypt(data) ──▶ ciphertext
aesKey ──▶ rsaEncrypt(platformPublicKey, exportedAesKey) ──▶ platformEnvelope
Store { ciphertext, platformEnvelope } together
Emergency access (platform only)
─────────────────────────────────
rsaDecrypt(platformPrivateKey, platformEnvelope) ──▶ exportedAesKey
importAesKey(exportedAesKey) ──▶ aesKey
aesDecrypt(aesKey, ciphertext) ──▶ plaintext
Next steps
- Getting Started — install and run your first encryption
- API Reference — full hook and utility documentation
- Examples — real-world usage patterns