How password encryption works: AES-GCM and PBKDF2

Your text and password inside AES-256-GCM with PBKDF2, byte by byte: why a weak password is the real risk, and what encryption cannot protect.

On this page

"Encrypt it with a password" sounds like one step. In a well-built tool it is three: turn the password into a key, encrypt the data with that key, and package everything the other side needs to reverse it. Each step has a reason, and each has a way to go wrong. This article follows a five-letter message through the text encrypt and decrypt tool byte by byte, then shows what the result does and does not protect you from.

The tool runs on the browser's built-in Web Crypto. Every number below was produced by its own code.

Step 1: a password is not a key

AES-256 needs a key of exactly 32 random-looking bytes. A password such as correct horse is 13 characters a person chose, which is neither the right length nor random. The bridge is a key derivation function. The tool uses PBKDF2 with HMAC-SHA-256 and 600,000 iterations, the figure OWASP's password storage guidance gives for this function.

Two details make the derivation safe:

  • A random 16-byte salt is mixed in. The same password gives a different key every time you encrypt, so an attacker cannot precompute a table of keys for common passwords and reuse it on everyone's files.
  • The 600,000 iterations make each guess expensive. On the laptop used for this article, one derivation took about 49 milliseconds in Node.js, against about 0.1 milliseconds at 1,000 iterations. That slowness costs you nothing when you type a password once, and it costs an attacker the same 49 ms for every single guess.

Before any of this, the password is normalised (Unicode NFKC). chào typed with a precomposed à is 4 characters, typed as a plus a combining accent it is 5, and they look identical. Without normalisation, the same password typed on a phone and on a laptop could produce different keys and a file that "will not open".

Step 2: AES-GCM encrypts and seals

AES-GCM does two jobs at once. It encrypts the data, and it computes a 16-byte authentication tag over the result. When you decrypt, the tag is checked first. If a single bit of the ciphertext, or of the header, has changed, decryption refuses to return anything.

GCM also needs a 12-byte nonce (IV) that must never repeat with the same key. The tool draws a fresh random one each time, and because the salt also changes the key, two encryptions of the same text never look alike. Encrypting hello twice with the same password gave two completely different 58-byte results.

Step 3: the envelope

The output has to carry everything except the password. For hello, the 58 bytes break down like this:

BytesContent
3the marker ENC
1format version (1)
4iteration count (600,000)
16the random salt
12the random nonce
1payload type (0 = text, 1 = file)
5the encrypted text hello
16the GCM tag

So the overhead is a fixed 53 bytes: Xin chào is 9 bytes in UTF-8 and becomes 62, and a 32-byte Vietnamese sentence becomes 85. As text, the envelope is written in Base64URL, four characters for every three bytes, so hello becomes 78 characters. Because the first bytes are always the same, every envelope made with the default settings starts with RU5DAQAJJ8: the ENC marker alone becomes RU5D, and the tool checks for that marker when you paste something in.

The whole 36-byte header is also fed into the GCM tag as "additional authenticated data". That stops a quiet downgrade: we rewrote the iteration count in a valid envelope from 600,000 to 1,000, and decryption failed exactly as if the password were wrong. An attacker cannot make your file cheaper to crack by editing it.

What a wrong password looks like

Three different changes all produced the same error in our tests: a password with one letter in the wrong case, one flipped bit in the ciphertext, and the edited iteration count. AES-GCM cannot tell "wrong password" from "damaged or tampered data"; both simply fail the tag check. That is by design. A tool that said "the password is close" or returned garbled text would be leaking information.

Where the real risk is: the password

Encryption with AES-256 is not the weak point. The password is, because an attacker who has your envelope can guess offline, as fast as their hardware allows, and nothing tells you it is happening.

A worked example with the 49 ms figure above, on one laptop core:

  • A 6-digit PIN has 1,000,000 possibilities: about 13.6 hours to try them all. A few machines finish in minutes.
  • Eight random lowercase letters give 26⁸, about 2.1 × 10¹¹: roughly 320 years on that one core, but attackers use many cores and graphics cards, so treat that as a floor, not a promise.
  • Four random words from a 7,776-word list give about 3.7 × 10¹⁵, over 17,000 times more than the eight letters.

The iteration count multiplies the attacker's work by a constant; the password's randomness multiplies it exponentially. Use a long random password or passphrase from the password generator, and see what makes a strong password for the arithmetic.

What encryption cannot protect

  1. The size. The envelope is 53 bytes longer than the content, so anyone can tell a short note from a long file.
  2. The password channel. Sending the envelope and the password in the same chat or e-mail protects nothing. Send the password another way, or agree it in person.
  3. The device. If malware or a screen-recorder is on the computer where you type the text, it sees the text before encryption.
  4. Forgetting. There is no reset and no back door. A lost password means the data is gone.
  5. Integrity of the tool. Encryption in a browser is only as trustworthy as the page's code. This tool sends nothing over the network, which you can check in the browser's network panel.

Common mistakes

  • Reusing a website password for an encrypted file. If that site leaks, the file is open.
  • Pasting the result into a place that changes characters, such as a word processor that swaps quotes or wraps lines. Base64URL survives most channels, but check that what arrives is identical.
  • Assuming encryption hides who sent it. The envelope carries no name, but the message around it does.

To try it, paste a sentence into the text encrypt and decrypt tool, encrypt, then decrypt with a password that differs by one character and watch it refuse.

Tools mentioned in this article

Back to the blog