Only Once Share
Web Crypto APIdevelopersencryption

Web Crypto API: Building Browser-Side Encryption

The Web Crypto API is a browser-native JavaScript API that provides cryptographic operations without any external libraries. It enables hardware-accelerated encryption, key generation, and hashing directly in the browser. Here's a practical guide for developers building privacy-focused applications.

Why Web Crypto API?

  • No external dependencies β€” Built into all modern browsers (Chrome, Firefox, Safari, Edge)
  • Hardware acceleration β€” Uses the CPU's AES-NI instruction set for fast encryption
  • Secure random number generation β€” crypto.getRandomValues() uses the OS's CSPRNG
  • Async design β€” Non-blocking operations via Promises
  • Key isolation β€” Non-extractable keys never leave the browser's crypto subsystem

Core Operations

1. Generating Random Values

// Generate a random 96-bit IV for AES-GCM
const iv = crypto.getRandomValues(new Uint8Array(12));

// Generate a random 256-bit value
const randomBytes = crypto.getRandomValues(new Uint8Array(32));

2. Generating an AES-256-GCM Key

const key = await crypto.subtle.generateKey(
  { name: "AES-GCM", length: 256 },
  true,  // extractable (set false for maximum security)
  ["encrypt", "decrypt"]
);

3. Encrypting Data

const encoder = new TextEncoder();
const data = encoder.encode("my secret message");
const iv = crypto.getRandomValues(new Uint8Array(12));

const ciphertext = await crypto.subtle.encrypt(
  {
    name: "AES-GCM",
    iv: iv,
    additionalData: encoder.encode("context-binding-data"),
    tagLength: 128
  },
  key,
  data
);

4. Decrypting Data

const plaintext = await crypto.subtle.decrypt(
  {
    name: "AES-GCM",
    iv: iv,
    additionalData: encoder.encode("context-binding-data"),
    tagLength: 128
  },
  key,
  ciphertext
);
const decoded = new TextDecoder().decode(plaintext);

5. Key Derivation with HKDF

// Import raw key material for HKDF
const keyMaterial = await crypto.subtle.importKey(
  "raw",
  masterKeyBytes,
  { name: "HKDF" },
  false,
  ["deriveKey"]
);

// Derive a per-message AES-256 key
const derivedKey = await crypto.subtle.deriveKey(
  {
    name: "HKDF",
    hash: "SHA-256",
    salt: saltBytes,
    info: new TextEncoder().encode(messageId)
  },
  keyMaterial,
  { name: "AES-GCM", length: 256 },
  false,
  ["encrypt", "decrypt"]
);

6. Exporting and Importing Keys

// Export to share (e.g., in a URL fragment)
const rawKey = await crypto.subtle.exportKey("raw", key);
const keyString = btoa(String.fromCharCode(...new Uint8Array(rawKey)));

// Import from shared key material
const importedKey = await crypto.subtle.importKey(
  "raw",
  keyBytes,
  { name: "AES-GCM", length: 256 },
  false,
  ["decrypt"]
);

Building a Zero-Knowledge Architecture

The Web Crypto API makes it straightforward to build zero-knowledge systems. The key design pattern used by Only Once Share:

  1. Generate a key in the browser
  2. Encrypt data client-side
  3. Send only ciphertext to the server
  4. Put the key in the URL fragment (#), which browsers never send to servers
  5. The recipient's browser reads the key from the fragment and decrypts

Common Mistakes

  • Using Math.random() for cryptographic purposes β€” Always use crypto.getRandomValues()
  • Reusing IVs β€” Generate a fresh random IV for every encryption operation
  • Putting keys in URL paths β€” Use URL fragments (#), not paths or query parameters, for keys
  • Ignoring AAD β€” Always use Additional Authenticated Data to bind context to ciphertext
  • Using extractable keys unnecessarily β€” Set extractable: false unless you need to export the key

Browser Support

The Web Crypto API is supported in all modern browsers: Chrome 37+, Firefox 34+, Safari 11+, Edge 12+. For older browsers, consider a fallback to a JavaScript implementation like asmcrypto.js, though this should be rare in 2025.

Conclusion

The Web Crypto API provides everything you need to build secure, privacy-first applications without external crypto libraries. For zero-knowledge architectures like secret sharing tools, it enables client-side AES-256-GCM encryption with hardware acceleration, HKDF key derivation, and secure random number generation β€” all natively in the browser.

Share secrets securely β€” for free

Only Once Share uses AES-256-GCM encryption with zero-knowledge architecture. No account required.

Try Only Once Share
All posts