security

Browser-Native Encryption with Web Crypto API and AES-256-CBC

Implement Zero-Knowledge cryptography using AES-256-CBC directly inside client web viewports.

15 Dec 202310 min read

Security-focused applications require zero-knowledge encryption: files and texts must be encrypted in the client viewport before transferring them over the internet. This prevents cloud operators and database servers from reading user data. This article explores how to implement secure, hardware-accelerated AES-256-CBC encryption using the browser's native Web Crypto API.

The Power of Web Crypto API

Modern browsers include the Web Crypto API (`window.crypto.subtle`), which executes cryptographic operations natively in compiled browser code. This is significantly faster and safer than importing large, third-party JavaScript libraries like CryptoJS, which lack hardware acceleration.

Generating the Encryption Key

First, we derive an encryption key from a user password. Using PBKDF2 (Password-Based Key Derivation Function 2) with a random salt secures the key against brute-force attacks.

async function deriveKey(password, salt) {
  const enc = new TextEncoder();
  const baseKey = await window.crypto.subtle.importKey(
    "raw",
    enc.encode(password),
    "PBKDF2",
    false,
    ["deriveKey"]
  );
  
  return window.crypto.subtle.deriveKey(
    {
      name: "PBKDF2",
      salt: salt,
      iterations: 100000,
      hash: "SHA-256"
    },
    baseKey,
    { name: "AES-CBC", length: 256 },
    false,
    ["encrypt", "decrypt"]
  );
}

Executing AES-256-CBC Encryption

We generate a random Initialization Vector (IV) for every encryption run, perform the native encryption, and return the IV combined with the ciphertext.

async function encryptData(plaintext, password) {
  const enc = new TextEncoder();
  const salt = window.crypto.getRandomValues(new Uint8Array(16));
  const iv = window.crypto.getRandomValues(new Uint8Array(16));
  
  const key = await deriveKey(password, salt);
  const ciphertext = await window.crypto.subtle.encrypt(
    { name: "AES-CBC", iv: iv },
    key,
    enc.encode(plaintext)
  );
  
  return { ciphertext, salt, iv };
}

// Summary

Zero-knowledge browser-native encryption using the Web Crypto API protects user assets from database breaches and network sniffers. Utilizing AES-256-CBC ensures enterprise-grade security with native browser performance.

#security#javascript#cryptography