Skip to content

horizonden-dev/react-e2ee

Repository files navigation

react-e2ee

Headless React hooks for client-side end-to-end encryption using the native Web Crypto API.

npm version license

Features

  • Zero dependencies — built entirely on the browser's SubtleCrypto API.
  • 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 localhost environments.

Installation

npm install react-e2ee
# or
pnpm add react-e2ee
# or
yarn add react-e2ee

Requires React 18+ and a browser with SubtleCrypto support (all modern browsers).

Quick Start

Asymmetric (RSA-OAEP)

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>;
}

Symmetric (AES-GCM)

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>;
}

API

useKeyPair()

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

useEncrypt({ publicKey })

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

useDecrypt({ privateKey })

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

useSymmetricKey()

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

useDigest()

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

useHmac()

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

useSign()

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

useFingerprint()

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

Utility Functions

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";

Security Notes

  • 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 localStorage without additional protection.

License

MIT © HorizonDen

About

Headless React hooks and utilities for client-side end-to-end encryption using the Web Crypto API

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors