Ask which encryption a product uses and you will usually be told a key length. AES-256 sounds twice as reassuring as AES-128, and the number is the part that makes it into marketing copy.
It is close to the least interesting thing about the system. The attacks that have actually broken deployed encryption over the last two decades did not brute-force a key. They exploited the fact that the ciphertext could be modified without anyone noticing.
Summary
Key length determines whether an attacker can read your data, and at 128 bits and above that question is already settled. The cipher mode determines whether an attacker can alter your data without detection. An unauthenticated mode fails silently — it hands back plaintext the attacker influenced — while an authenticated mode returns an error. Choose the mode carefully; the key length is close to a free parameter.
The number nobody needs to worry about
AES-128 has 2¹²⁸ possible keys. That is roughly 3.4 × 10³⁸.
There is a standard way of conveying how large this is and it is worth doing once. Suppose you had hardware testing a trillion keys per second, and a billion such machines. Running since the formation of the Earth, you would have searched an utterly negligible fraction of the space. There is no engineering progress that changes this, because the limits involved are thermodynamic rather than technological.
AES-256 is not twice as hard. It is 2¹²⁸ times as hard — a number with no physical meaning. Both are, for the purpose of brute force, simply out of reach.
This is not an argument against AES-256. It costs a few percent more in performance and there is no reason not to use it; this site does, and the AES-256 feature page sets out the exact parameters. It is an argument that once you are at 128 bits or above, the key length has stopped being the variable that decides whether the system is safe, and continuing to talk about it distracts from the variable that does.
The thing that actually goes wrong
Encryption gives you confidentiality: an attacker cannot read the message. On its own, it says nothing about integrity — whether an attacker can change the message.
With many cipher modes, they can. The property is called malleability, and in some modes it is remarkably precise.
Take AES in CBC mode without any separate integrity check. An attacker who does not know the key, and cannot read a word of the plaintext, can still flip specific bits in one ciphertext block and cause predictable, chosen changes in the next block of decrypted plaintext. They are not decrypting anything. They are making controlled edits to a message they cannot read.
The recipient decrypts it and gets plaintext. Not an error — plaintext. There is no check to fail, so nothing signals that anything happened.
Padding oracles, and why this is not theoretical
The best-documented consequence is the padding oracle attack, described by Serge Vaudenay in 2002 and then found in deployed systems for the next fifteen years.
The mechanism: block ciphers need input in whole blocks, so short messages are padded. On decryption, the padding is checked and stripped. If the system behaves differently when the padding is malformed — a distinct error message, a different HTTP status, or merely a measurably different response time — that difference is one bit of information about the plaintext.
One bit is enough. An attacker submits modified ciphertexts, observes which are accepted, and recovers the plaintext a byte at a time. A few thousand requests recovers a block. No key is ever guessed.
This is the class of flaw behind POODLE against SSL 3.0 in 2014, and behind a long series of framework-level vulnerabilities before and after it. Every one of them ran correct AES with an adequate key length.
What an authentication tag does
Authenticated encryption — AEAD, for authenticated encryption with associated data — solves this by computing a tag over the ciphertext as part of encrypting, and verifying that tag before attempting to decrypt.
Under AES-GCM, the tag is 128 bits appended to the ciphertext. On decryption the tag is recomputed and compared. If a single bit of the ciphertext was altered, the comparison fails, and the operation returns an error rather than plaintext.
Two properties of that make it work where bolted-on integrity checks historically did not.
The verification happens first. The padding is never examined for a message that failed authentication, so there is no oracle to query — the attacker's modified ciphertexts all produce the same undifferentiated failure.
The comparison is constant-time. A tag check that short-circuits on the first differing byte leaks how much of a forgery was correct, which is enough to construct one incrementally. Correct AEAD implementations, including the browser's, compare in time independent of the data.
The alternative — encrypt with one primitive, then MAC with another — can be done correctly, and encrypt-then-MAC is the order to use. It is also where a great many implementations have gone wrong, by choosing MAC-then-encrypt, by comparing tags with ==, or by forgetting the MAC on one code path. A mode that cannot be assembled in the wrong order is a better default than a construction that can.
What to actually use
| Mode | Authenticated | Use it? |
|---|---|---|
| AES-GCM | Yes | Yes — hardware-accelerated, ubiquitous, in the Web Crypto API |
| ChaCha20-Poly1305 | Yes | Yes — preferable where AES hardware acceleration is absent |
| AES-CBC + HMAC (encrypt-then-MAC) | Yes, if built correctly | Only where AEAD is unavailable |
| AES-CBC alone | No | No |
| AES-CTR alone | No | No — malleable, and bit-flips are direct |
| AES-ECB | No | Never — identical plaintext blocks produce identical ciphertext |
The two AEAD options at the top are the answer in nearly every case. RFC 5116 defines the AEAD interface; NIST SP 800-38D specifies GCM; RFC 8439 specifies ChaCha20-Poly1305.
TLS 1.3 made this decision for the entire web in RFC 8446: every cipher suite it permits is AEAD. The unauthenticated CBC suites were removed rather than deprecated, because two decades of evidence showed they would be misused.
The one way to break GCM
Authenticated encryption is not unconditionally safe. GCM has a hard requirement, and violating it is not a weakening but a break.
The initialisation vector must never repeat under the same key.
Encrypt two different messages with the same key and the same nonce and an attacker who holds both ciphertexts can recover the XOR of the plaintexts. Worse, they can recover the authentication subkey, at which point they can forge tags for messages of their choosing — the integrity guarantee is gone entirely, not merely reduced.
The practical rules are short. Generate the IV with a CSPRNG inside the encryption function. Never reuse a variable across calls. Never derive it deterministically from the message or a counter you might restart. Twelve random bytes per encryption is the standard, and the Web Crypto API article shows where that sits in the call sequence.
If you genuinely cannot guarantee nonce uniqueness — a distributed system with no coordination, say — use a nonce-misuse-resistant mode such as AES-GCM-SIV (RFC 8452) instead of hoping.
What authenticated encryption does not give you
It does not authenticate the sender. The tag proves the message was produced by someone holding the key and has not been altered since. With a shared symmetric key, that is anyone who has it. Proving which party sent something requires signatures.
It does not prevent replay. A message captured intact and re-sent later verifies perfectly, because it is genuinely unaltered. Preventing replay needs sequence numbers or timestamps inside the authenticated data.
It does not hide metadata. Length, timing and the fact that a message exists are all visible. Encryption protects content, not the shape of the traffic.
It does not fix a weak key. All of this assumes the key came from somewhere sound. If it was derived from a guessable password with a fast hash, the mode is irrelevant — salting and key derivation cover that half.
What to ask instead of "how many bits?"
Next time a product tells you it uses AES-256, the useful follow-up is not about the key.
It is: which mode? If the answer is GCM or ChaCha20-Poly1305, integrity is handled. If the answer is CBC, ask what provides the integrity check and in what order it is applied. If nobody can answer, the number of bits in the key was never the thing protecting you.
How to judge an encrypted note service sets out the rest of the questions worth asking, and what the answers actually reveal.
FAQ: authenticated encryption
Q1. Is AES-256 more secure than AES-128?
Against brute force, both are already out of reach, and the difference has no practical meaning. AES-256 has a larger margin against future cryptanalytic progress and costs a few percent more in performance, so it is a reasonable default — but it is not the parameter deciding whether a system is safe.
Q2. What does AEAD stand for?
Authenticated encryption with associated data. It means the mode provides confidentiality and integrity together, and can additionally authenticate unencrypted context — a header or record identifier — so that cannot be swapped either.
Q3. Is AES-CBC broken?
CBC itself is not broken as a mode, but using it without a separate integrity check leaves the ciphertext malleable, and that is the root of the padding-oracle family of attacks. Where you must use it, apply encrypt-then-MAC with a constant-time comparison. Where you can choose, use an AEAD mode instead.
Q4. Why is reusing a GCM nonce so serious?
Because it leaks more than a single message. Two ciphertexts under the same key and nonce reveal the XOR of their plaintexts, and they also allow recovery of the authentication subkey — after which an attacker can forge valid tags. The integrity guarantee is not weakened, it is gone.
Q5. Is ChaCha20-Poly1305 better than AES-GCM?
Neither is better in general. AES-GCM is faster where the processor has AES instructions, which covers most desktops and modern phones. ChaCha20-Poly1305 is faster in software without them and is less prone to timing side channels in naive implementations. Both are sound choices.
Q6. Does HTTPS already give me authenticated encryption?
For data in transit, yes — TLS 1.3 permits only AEAD cipher suites. That protects the connection, not the stored record. Once data is at rest on a server, its protection depends on how that server encrypted it, which is the subject of client-side vs server-side encryption.
Where to go next
- How the Web Crypto API works in the browser — where the tag and the IV sit in a real call sequence.
- AES vs RSA encryption — the symmetric and asymmetric families, and why real systems use both.
- What is a salt, and why does every record need its own? — the other half of getting the inputs right.
- AES-256-GCM on Inkrypt — the exact mode, key length and IV handling this site runs.