Headless React hooks for client-side end-to-end encryption using the native Web Crypto API.
- Zero dependencies — built entirely on the browser's
SubtleCryptoAPI. - Headless — pure hooks & utilities, no UI imposed on you.
- RSA-OAEP asymmetric encryption for key exchange and small payloads.
- AES-GCM symmetric encryption for large payloads (with random IV per call).
- ECDSA digital signatures (P-256, P-384, P-521).
- HMAC message authentication (SHA-256 / SHA-384 / SHA-512).
- SHA hashing — SHA-1, SHA-256, SHA-384, SHA-512 digest utilities.
- Key fingerprinting — human-readable colon-separated hex fingerprints.
- TypeScript-first — full type definitions included.
- Secure context — works in HTTPS and
localhostenvironments.
npm install react-e2ee
# or
pnpm add react-e2ee
# or
yarn add react-e2eeRequires React 18+ and a browser with
SubtleCryptosupport (all modern browsers).
import { useKeyPair, useEncrypt, useDecrypt } from "react-e2ee";
function Demo() {
const { keyPair, generating, generate, serialized } = useKeyPair();
const { encrypt, encrypting } = useEncrypt({ publicKey: keyPair?.publicKey });
const { decrypt, decrypting } = useDecrypt({ privateKey: keyPair?.privateKey });
const run = async () => {
await generate();
const ciphertext = await encrypt("Hello, E2E world!");
const plaintext = await decrypt(ciphertext);
console.log(plaintext); // "Hello, E2E world!"
};
return <button onClick={run} disabled={generating}>Run demo</button>;
}import { useSymmetricKey } from "react-e2ee";
function SymDemo() {
const { generate, encrypt, decrypt, exportedKey } = useSymmetricKey();
const run = async () => {
await generate();
const ciphertext = await encrypt("Large payload...");
const plaintext = await decrypt(ciphertext);
console.log(plaintext);
};
return <button onClick={run}>Run symmetric demo</button>;
}Manages an RSA-OAEP key pair.
| Property / Method | Type | Description |
|---|---|---|
keyPair |
CryptoKeyPair | null |
The native key pair |
serialized |
SerializedKeyPair | null |
Base64-encoded public + private key |
generating |
boolean |
True while generating or importing |
error |
Error | null |
Last error |
generate() |
() => Promise<void> |
Generate a new key pair |
importKeyPair(s) |
(s: SerializedKeyPair) => Promise<void> |
Re-import a saved key pair |
clear() |
() => void |
Clear state |
Encrypt data with an RSA-OAEP public key.
| Property | Type | Description |
|---|---|---|
encrypt(data) |
(data: string | ArrayBuffer) => Promise<string> |
Returns Base64 ciphertext |
encrypting |
boolean |
True while encrypting |
error |
Error | null |
Last error |
Decrypt data with an RSA-OAEP private key.
| Property | Type | Description |
|---|---|---|
decrypt(ciphertext) |
(ciphertext: string) => Promise<string> |
Returns plaintext |
decrypting |
boolean |
True while decrypting |
error |
Error | null |
Last error |
Manages an AES-GCM 256-bit symmetric key.
| Property / Method | Type | Description |
|---|---|---|
key |
CryptoKey | null |
The native key |
exportedKey |
string | null |
Base64 raw key for storage |
generating |
boolean |
True while generating or importing |
error |
Error | null |
Last error |
generate() |
() => Promise<void> |
Generate a new key |
importKey(base64) |
(base64: string) => Promise<void> |
Import a stored key |
encrypt(data) |
(data: string | ArrayBuffer) => Promise<string> |
AES-GCM encrypt (IV prepended) |
decrypt(ciphertext) |
(ciphertext: string) => Promise<string> |
AES-GCM decrypt |
clear() |
() => void |
Clear state |
Stateless SHA hashing.
| Property / Method | Type | Description |
|---|---|---|
digest(data, algorithm?) |
(data: string | ArrayBuffer, algorithm?: DigestAlgorithm) => Promise<string> |
Returns Base64 digest. Default: SHA-256 |
digesting |
boolean |
True while hashing |
error |
Error | null |
Last error |
HMAC key management and message authentication. Hash algorithm is specified when calling generate(hash?).
| Property / Method | Type | Description |
|---|---|---|
key |
CryptoKey | null |
The native HMAC key |
exportedKey |
string | null |
Base64-encoded raw key |
generating |
boolean |
True while generating or importing |
error |
Error | null |
Last error |
generate(hash?) |
(hash?: HmacHash) => Promise<void> |
Generate a new HMAC key. Default: SHA-256 |
importKey(base64) |
(base64: string) => Promise<void> |
Import a stored key |
sign(data) |
(data: string | ArrayBuffer) => Promise<string> |
Returns Base64 signature |
verify(signature, data) |
(sig: string, data: string | ArrayBuffer) => Promise<boolean> |
Verify a signature |
clear() |
() => void |
Clear state |
ECDSA key pair management and digital signatures. Curve is specified when calling generate(curve?).
| Property / Method | Type | Description |
|---|---|---|
keyPair |
CryptoKeyPair | null |
The native ECDSA key pair |
serialized |
{ publicKey: string; privateKey: string } | null |
Base64-encoded keys |
generating |
boolean |
True while generating or importing |
error |
Error | null |
Last error |
generate(curve?) |
(curve?: EcCurve) => Promise<void> |
Generate a new ECDSA key pair. Default: P-256 |
importKeyPair(s) |
(s: { publicKey: string; privateKey: string }) => Promise<void> |
Re-import saved keys |
sign(data) |
(data: string | ArrayBuffer) => Promise<string> |
Returns Base64 signature |
verify(signature, data, publicKey?) |
(sig: string, data: string | ArrayBuffer, pk?: CryptoKey) => Promise<boolean> |
Verify with own or external key |
clear() |
() => void |
Clear state |
Key fingerprinting.
| Property / Method | Type | Description |
|---|---|---|
fingerprint(key, algorithm?) |
(key: CryptoKey | string, algorithm?: DigestAlgorithm) => Promise<string> |
Returns colon-separated uppercase hex fingerprint. Default: SHA-256 |
error |
Error | null |
Last error |
Low-level helpers are also exported for custom use:
import {
// RSA
generateRsaKeyPair, exportRsaPublicKey, exportRsaPrivateKey,
importRsaPublicKey, importRsaPrivateKey,
rsaEncrypt, rsaDecrypt,
encryptRsaPrivateKey, decryptRsaPrivateKey,
// AES
generateAesKey, exportAesKey, importAesKey,
aesEncrypt, aesDecrypt,
// Hashing & Fingerprint
digest, fingerprint, bufferToHex,
// HMAC
generateHmacKey, exportHmacKey, importHmacKey,
hmacSign, hmacVerify,
// ECDSA
generateEcdsaKeyPair, exportEcdsaPublicKey, exportEcdsaPrivateKey,
importEcdsaPublicKey, importEcdsaPrivateKey,
ecdsaSign, ecdsaVerify,
// Encoding
bufferToBase64, base64ToBuffer, encodeText, decodeText,
} from "react-e2ee";- Keys are generated and never leave the browser unless you explicitly serialize and transmit them.
- Uses RSA-OAEP with 2048-bit keys and SHA-256 for asymmetric operations.
- Uses AES-GCM with 256-bit keys and a random 96-bit IV per message for symmetric operations.
- Uses ECDSA (P-256 / P-384 / P-521) for digital signatures with automatic hash selection.
- Uses HMAC (SHA-256 / SHA-384 / SHA-512) for message authentication codes.
- Only works in secure contexts (HTTPS or
localhost). - Private keys should be stored securely (e.g., encrypted storage, HSM) — never in plain
localStoragewithout additional protection.
MIT © HorizonDen