AES is a block cipher, not a complete encryption scheme
AES (Advanced Encryption Standard, the standardised name for the Rijndael cipher) takes a 16-byte block of plaintext and a key (16, 24, or 32 bytes for AES-128, AES-192, AES-256) and produces a 16-byte block of ciphertext. That's all it does. Feed it the same block and the same key, you get the same ciphertext every time. It is a permutation, not an encryption scheme.
Most real messages are longer than 16 bytes. To encrypt a 4 KB file with AES, you need a way to chain multiple 16-byte block operations together while keeping the result secure. That 'way' is called a mode of operation, and it is where almost every catastrophic AES bug lives.
When someone says 'we encrypt with AES-256', the load-bearing word is missing — which mode? AES-256-ECB is functionally broken for most purposes. AES-256-CBC is fine for confidentiality but doesn't detect tampering. AES-256-GCM gives you both.
Why ECB is broken (and why the famous penguin matters)
ECB (Electronic Codebook) is the simplest mode: split the plaintext into 16-byte blocks, encrypt each one independently with the same key. The flaw is visible at a glance — any two identical plaintext blocks produce identical ciphertext blocks. Patterns in the input survive into the output.
The textbook demonstration is the Tux penguin: take a bitmap of the Linux mascot, encrypt the raw pixel data with AES-ECB, render the ciphertext back as a bitmap. The penguin is still recognisable, because flat regions of the original image — solid black, solid white — encrypt to repeating blocks in the output. ECB doesn't hide structure; it just substitutes one alphabet for another.
CBC (Cipher Block Chaining) fixes this by XOR-ing each plaintext block with the previous ciphertext block before encrypting, starting from a random IV. CTR (Counter) mode turns the block cipher into a stream cipher by encrypting a counter and XOR-ing the result with plaintext. Both are fine for confidentiality. Neither detects tampering — flip a ciphertext bit in CTR mode and you flip the corresponding plaintext bit on decryption, silently.
GCM, AEAD, and what authenticated encryption gives you
GCM (Galois/Counter Mode) is CTR mode plus an authentication tag — a 16-byte MAC computed over the ciphertext (and any associated data you want bound to it, like a user id or a content type). On decryption, the receiver recomputes the tag and refuses to decrypt if it doesn't match.
That property — confidentiality plus integrity plus authenticity in a single primitive — is called AEAD (Authenticated Encryption with Associated Data). It is what you want for almost every encryption task. A bit-flip in the ciphertext doesn't produce garbled plaintext; it produces a refusal to decrypt at all.
The cost of all that is one harsh constraint: nonce reuse is catastrophic. If you encrypt two different messages with the same key and the same 96-bit nonce, an attacker who sees both ciphertexts can recover the authentication subkey and, with it, forge tags for arbitrary messages. The confidentiality of the two messages also leaks. Always generate a fresh random nonce per message, or use a counter you can guarantee never repeats per key.
Salts, nonces, and turning a password into a key
AES-256 needs a 32-byte key with 256 bits of entropy. Humans don't have 256-bit passwords. So when you want to encrypt with a user-supplied passphrase, you run that passphrase through a key derivation function (KDF) that stretches it into a key while making brute-force attacks expensive.
PBKDF2 is the oldest standardised choice. The OWASP cheat sheet currently recommends 600,000 iterations for PBKDF2-SHA256 in 2026. It's fine, it's available in SubtleCrypto, and it's broken in one specific way: it has no memory cost. The right answer for new systems in 2026 is Argon2id, the winner of the 2015 Password Hashing Competition, designed to be slow and memory-hard.
Salt vs nonce. A salt is fed to the KDF along with the password so the same password produces different keys for different users; it prevents pre-computed rainbow tables. A nonce (number used once) is fed to the cipher mode (GCM) to ensure different ciphertexts for the same plaintext-key pair. Both must be present in your encrypted blob — they're not secret, but they must be retrievable for decryption.
AES-GCM vs ChaCha20-Poly1305
ChaCha20-Poly1305 is the other modern AEAD you'll see — it's the default cipher suite for OpenSSH, an option in TLS 1.3, and the underlying cipher in WireGuard. Functionally, it gives you the same guarantee as AES-GCM.
On hardware with AES-NI (essentially every laptop, server, and recent phone since around 2012), AES-GCM is faster. On hardware without AES acceleration, ChaCha20-Poly1305 is faster, often by a wide margin. ChaCha20 also has a wider nonce (24 bytes for XChaCha20) which makes random-nonce generation strictly safer than GCM's 96 bits.
The pragmatic rule: if you control the deployment and it's all modern hardware, AES-GCM. If you're encrypting on mobile or embedded, ChaCha20-Poly1305. SubtleCrypto in browsers only exposes AES-GCM directly. SnapToolz's AES tool runs SubtleCrypto AES-256-GCM with PBKDF2 key derivation entirely in your browser tab — no upload, key handle stays non-extractable.
Tools used in this guide
FAQ
- Is AES-256 actually meaningfully stronger than AES-128?
- Against classical computers, no — AES-128 already has 128 bits of security, which is far beyond anything brute-forceable in this century. AES-256 was specified partly to give a comfort margin against future quantum attacks (Grover's algorithm halves the effective key strength, so AES-256 retains 128-bit post-quantum security). For new systems, AES-256-GCM is the conservative default.
- Can I just use the same nonce every time if my key is strong?
- No. Nonce reuse in GCM is catastrophic regardless of key strength — it leaks plaintext relationships and allows tag forgery. This is not a theoretical concern; real production systems have been broken this way. Always generate a fresh random 12-byte nonce per message.
- What's the right iteration count for PBKDF2 in 2026?
- OWASP currently recommends 600,000 iterations for PBKDF2-SHA256 and 210,000 for PBKDF2-SHA512. Calibrate to your slowest target device — the goal is roughly 100 ms of derivation time on the weakest hardware your users will run. If you can use Argon2id instead, do — it's the modern recommendation.
- How do I send an encrypted file to someone safely?
- Encrypt with a strong passphrase, transmit the ciphertext over any channel (email is fine — the recipient sees only ciphertext), and transmit the passphrase out of band — a phone call, a different messenger, in person. Never put the ciphertext and the passphrase in the same message.