Back to Security Insights

AES-256-GCM in the browser: a quick tour of our crypto stack

We use the Web Crypto API with AES-GCM. Here’s what that means and why we chose it.

Inkrypt · Security Insights

All encryption and decryption use the SubtleCrypto interface (the Web Crypto API). We use AES-256-GCM: a 256-bit key in Galois/Counter Mode, which gives both confidentiality and authentication. If someone flips a bit in the ciphertext, decryption fails—no silent corruption.

Why GCM and not CBC

CBC is still common but is easy to misuse (IV reuse, padding oracles). GCM is an AEAD mode: authenticated encryption with associated data. You get an authentication tag that we store with the ciphertext; on decrypt, the browser verifies the tag before returning any plaintext. We also use a fresh random IV for every encryption operation, so we avoid the pitfalls of IV reuse.

How the browser actually encrypts

In practice, encrypting a note looks like this:

1. Your browser derives a 256-bit key from your password using PBKDF2 (310,000 iterations) and a random salt.

2. A random IV is generated for the operation.

3. The note content is encrypted with AES-256-GCM using that key and IV.

4. The browser returns ciphertext plus an authentication tag; we send those, along with salt and IV, to the server.

The key itself never leaves your browser tab and is discarded once the operation is done.

Key derivation

The key comes from PBKDF2 with SHA-256, 310,000 iterations, and a random salt. So the “key” the user has is really a password; we turn it into a proper 256-bit key in the browser and never send that key anywhere. High iteration counts make brute-force attacks expensive, especially when combined with strong, unique passwords.

What the server sees

From the server’s point of view, a saved note is:

  • A slug (from the URL).
  • Ciphertext produced by AES-256-GCM.
  • The PBKDF2 salt and KDF parameters (including the 310k iteration count).
  • The AES-GCM IV and authentication tag.

There is no password, no derived key, and no plaintext stored on the backend. Even if the database leaks, attackers see only random-looking bytes protected by PBKDF2 and AES-256-GCM.

FAQ: AES-256-GCM in the browser

Q1. Why did you choose AES-256-GCM instead of another mode?

AES-256-GCM gives us both confidentiality and integrity in one primitive, and it’s well supported and often hardware-accelerated in modern browsers. That makes it a safer, more efficient choice than older modes like CBC, which are easy to misuse.

Q2. What happens if someone tampers with the ciphertext?

On decrypt, the browser verifies the GCM authentication tag. If any bit of the ciphertext, IV, or tag is modified, verification fails and decryption throws—there’s no “best-effort” corrupted plaintext.

Q3. Why do you generate a new IV for every encryption?

Reusing an IV with AES-GCM can leak information about the plaintext and undermine security. A fresh random IV for each save keeps each ciphertext unique, even if the same note is encrypted multiple times with the same key.

Q4. How does PBKDF2 with 310,000 iterations protect my password?

PBKDF2 slows down each password guess by running 310,000 hash operations. That cost is negligible for you when you unlock a note, but very expensive for an attacker trying millions or billions of guesses.

Q5. Can you or an attacker derive my key from your database?

No. We store only ciphertext, salt, IV, and KDF parameters. Without your password, PBKDF2 can’t be reversed, and AES-256-GCM can’t be decrypted—so both we and an attacker with our database are stuck.

Where to go next

If you want to dig deeper into how this fits into the rest of the system:

Or just try it yourself in Inkrypt at https://www.inkrypt.online and see how AES-256-GCM in the browser feels in practice.