Learn · Technologies we use
How AES works, round by round
How the cipher under every cipher.ink message scrambles 16 bytes, with the standard's own worked numbers.
AES, the Advanced Encryption Standard, protects almost everything that's encrypted today: your Wi-Fi, your bank's website, your phone's storage and every message sealed on cipher.ink, which uses AES-256-GCM. It takes 16 bytes and a key and scrambles the bytes in ten, twelve or fourteen identical rounds of four small steps. Each step is simple enough to follow by hand, so below we walk through one real round with real numbers and then look at why those steps, repeated, are so hard to undo.
Where AES came from
By the late 1990s the old standard, DES, had a 56-bit key that specialized hardware could search in days. The US National Institute of Standards and Technology (NIST) ran an open competition to replace it, and fifteen designs from around the world were picked over in public for about five years. The winner was Rijndael, by two Belgian cryptographers, Joan Daemen and Vincent Rijmen. NIST published it, with a fixed 128-bit block, as FIPS 197 on 26 November 2001, and it became a US federal standard on 26 May 2002. Three key sizes are allowed, and the number of rounds depends on the key:
| Variant | Key | Block | Rounds |
|---|---|---|---|
| AES-128 | 128 bits | 128 bits | 10 |
| AES-192 | 192 bits | 128 bits | 12 |
| AES-256 | 256 bits | 128 bits | 14 |
The competition matters to the story. DES was designed largely out of public view, while AES was chosen after years of attack by the world's cryptographers. Two decades on, it hasn't just survived. It's one of the most heavily analyzed ciphers in history.
The state: 16 bytes in a grid
AES works on a block of 16 bytes and arranges them as a 4×4 grid called the state. The bytes go into the grid column by column, so the first four fill the first column, the next four the second, and so on.
Every round applies four steps to that grid: SubBytes, ShiftRows, MixColumns and AddRoundKey. One extra AddRoundKey comes before round 1, and the last round skips MixColumns. The picture below is round 1 of the worked example in FIPS 197 (the key 2b7e1516 28aed2a6 abf71588 09cf4f3c and the plaintext 3243f6a8 885a308d 313198a2 e0370734), with the real bytes after each step.
SubBytes: the only non-linear step
SubBytes swaps each of the 16 bytes for another byte, using a 256-entry lookup table called the S-box. The table looks arbitrary, but it isn't random. Each entry is built in two stages.
- Invert in a finite field. Treat the byte as a polynomial of degree 7 with coefficients 0 or 1, and take its multiplicative inverse modulo the polynomial x8 + x4 + x3 + x + 1 (zero maps to zero). Multiplication in this field is ordinary polynomial multiplication with the coefficients added by XOR, reduced whenever the degree reaches 8. The standard's own example shows
57 × 13 = fein this field. The inverse of53isca, because53 × ca = 01. - Scramble the bits. Apply a fixed linear map, then XOR with
63. The inversecabecomesed. So the S-box sends53toed, and00to63.
The inversion is what lets the cipher stand up to the two most powerful general attacks, differential and linear cryptanalysis. Inversion in this field is about as far from a linear function as a function on bytes can get. The second stage removes the fixed points and the simple algebraic description the inversion would have on its own. This site's test suite builds the whole table from that definition and checks it against the standard.
ShiftRows and MixColumns: spreading the damage
With only SubBytes, each byte would stay where it was and the cipher would amount to 16 separate lookups. ShiftRows and MixColumns spread every byte's influence across the whole grid.
ShiftRows leaves row 0 alone and rotates row 1 left by one place, row 2 by two and row 3 by three. Afterward, the four bytes that shared a column sit in four different columns.
MixColumns treats each column as four field elements and multiplies by a fixed 4×4 matrix of small numbers (2, 3, 1, 1 in a rotating pattern). Each output byte is the XOR of the column's four input bytes, each multiplied by 1, 2 or 3 in the field. For example, the column db 13 53 45 becomes 8e 4d a1 bc. After MixColumns, every output byte depends on all four bytes of its column. ShiftRows then moves those bytes to different columns, and after one more MixColumns each byte depends on all 16.
The result is diffusion. In our example, flipping one bit of the plaintext changes this many of the 128 state bits after each round: 1 after the first AddRoundKey, then 19, 70, 62, 68, 68, 61, 67, 65, 75 and 68 at the end. Within two rounds about half the bits have changed, and they keep changing. That's the avalanche property, and it's what ten rounds are for. A few rounds mix the data thoroughly, and the rest buy a wide margin over every known attack.
AddRoundKey and the key schedule
AddRoundKey XORs the state with a 16-byte round key, and it's the only place the key enters. The key schedule stretches the original key into a different round key for each round. In the example, round key 0 is the key itself, 2b7e1516 28aed2a6 abf71588 09cf4f3c, and round key 1 is a0fafe17 88542cb1 23a33939 2a6c7605. Each new 4-byte word is the XOR of the word four positions back and the previous word. Every fourth word is first rotated by a byte, passed through the S-box and XORed with a round constant. The constant keeps any two rounds from being symmetric, and the S-box makes the schedule non-linear, so knowing one round key doesn't hand you the others.
How secure is it?
No practical attack is known against AES as it's actually used. The best published attacks on the full cipher, the biclique attacks by Bogdanov, Khovratovich and Rechberger in 2011 (improved slightly in 2015), need about 2126.2 operations for AES-128, 2190.2 for AES-192 and 2254.6 for AES-256. That saves a factor of only two to four over brute force. They're academic results and no threat. Related-key attacks on AES-192 and AES-256 (2009) run faster, but they need keys related in a chosen way, which a well-designed protocol never allows.
Brute force is hopeless. 2128 is about 3.4 × 1038. A machine that tried 1018 keys a second, a billion times faster than anything that exists, would need about 1013 years, some 780 times the age of the universe. AES-256 has 2256 keys, a number with 78 digits. Quantum computers don't change this much. Grover's algorithm searches a key space in roughly the square root of the time, so AES-256 would still need about 2128 steps. That's one reason this site uses 256-bit keys (post-quantum cryptography).
What breaks AES in practice is the implementation, not the cipher. Table-lookup software can leak the key through the time it takes, because memory caches respond differently to different lookups. Daniel Bernstein demonstrated a cache-timing attack on a server in 2005, and Osvik, Shamir and Tromer recovered a full key after 800 encryptions in a lab setting the same year. Modern processors have dedicated AES instructions (AES-NI) that run in constant time and are far faster, at around 1 to 2 cycles per byte. That's why browsers use the hardware.
What AES leaves out
- AES is a block cipher, and 16 bytes isn't a message. To encrypt more than 16 bytes you need a mode. Encrypting each block separately (ECB) leaks patterns: see the ECB picture demo. Counter mode and CBC avoid that.
- AES doesn't check that a message is unchanged. That's the job of an authenticated mode such as GCM, which adds a tag (AES-GCM, explained).
- AES doesn't turn a passphrase into a key. A short passphrase is a weak key whatever the cipher. cipher.ink runs your passphrase through PBKDF2 first.
How cipher.ink uses it
Every message is sealed in your browser with AES using a 256-bit key, in Galois/Counter Mode, with a fresh 12 bytes (96 bits) nonce and a 128-bit authentication tag. Our code calls the browser's built-in Web Crypto API and never touches the cipher itself, so it runs on the processor's AES instructions. You can read the exact lines on the code page. The round-by-round implementation that drives the tools here is a separate, teaching version, checked against the standard's test vectors.
Further reading
- FIPS 197: Advanced Encryption Standard (2001)
- Daemen and Rijmen: The Design of Rijndael (Springer, 2002)
- Bogdanov, Khovratovich, Rechberger: Biclique Cryptanalysis of the Full AES (2011)
- Bernstein: Cache-timing attacks on AES (2005)
- Osvik, Shamir, Tromer: Cache Attacks and Countermeasures: the Case of AES (2005)
- Biryukov and Khovratovich: Related-key Cryptanalysis of the Full AES-192 and AES-256 (2009)