After completing this tutorial, you should be able to:
The Advanced Encryption Standard (AES) is the successor to DES and the most widely used symmetric block cipher in the world. Adopted by NIST in 2001 after a five-year public competition, AES is a substitution-permutation network (SPN) that operates on 128-bit blocks with key sizes of 128, 192, or 256 bits. It is the encryption standard for U.S. government classified information (when used with 192- or 256-bit keys) and is used in countless applications, from TLS/SSL to disk encryption to wireless security.
AES was designed by Joan Daemen and Vincent Rijmen, two Belgian cryptographers, and was originally named Rijndael (a portmanteau of their names). It was selected from five finalists (Rijndael, Serpent, Twofish, RC6, and MARS) for its combination of security, performance, and flexibility.
In this tutorial, we will explore the internal structure of AES in detail. We begin with the finite field arithmetic that underpins AES—GF(2⁸) with the irreducible polynomial x⁸ + x⁴ + x³ + x + 1. We then examine each of the four transformations: SubBytes (non-linear substitution), ShiftRows (byte permutation), MixColumns (linear diffusion), and AddRoundKey (key XOR). We cover the key schedule and discuss decryption. Finally, we analyze the security of AES and its implementation considerations.
In Tutorial 2.4, we introduced SPN and Feistel structures; AES is the premier example of an SPN. Tutorial 2.5 covered DES, and this tutorial allows direct comparison. Tutorial 2.7 will cover block cipher modes, which show how AES is used in practice.
The NIST Competition (1997–2001):
Why Rijndael won:
AES processes data in a 4×4 byte array called the state. The state is initialized from the plaintext and transformed through a series of rounds, each applying four transformations (except the final round, which omits MixColumns).
Figure 1: Overall AES encryption process.
AES operates on bytes using arithmetic in the finite field GF(2⁸). The field is defined using the irreducible polynomial:
m(x) = x⁸ + x⁴ + x³ + x + 1 (0x11B in hex)
A byte is represented as a polynomial of degree ≤ 7 with coefficients in GF(2). For example, the byte 0x57 (binary 01010111) represents:
x⁶ + x⁴ + x² + x + 1
Addition in GF(2⁸) is bitwise XOR. For example:
0x57 ⊕ 0x83 = 0xD4
Multiplication is polynomial multiplication modulo m(x). AES defines the xtime operation (multiplication by x, or 0x02) as a left shift followed by a conditional XOR with 0x1B if the most significant bit was set.
xtime(byte):
if (byte & 0x80) {
byte = (byte << 1) ^ 0x1B;
} else {
byte = byte << 1;
}
Multiplication by any value can be expressed as a combination of xtime operations.
The AES state is a 4×4 array of bytes, arranged in column-major order (first byte is the first column, top row).
Input bytes: s₀, s₁, s₂, …, s₁₅
State:
| s₀ | s₄ | s₈ | s₁₂ |
| s₁ | s₅ | s₉ | s₁₃ |
| s₂ | s₆ | s₁₀ | s₁₄ |
| s₃ | s₇ | s₁₁ | s₁₅ |
This column-major ordering is important for the ShiftRows and MixColumns transformations.
Each round (except the final) applies four transformations in order:
The number of rounds depends on the key size:
| Key Size | Number of Rounds | Key Schedule Words |
|---|---|---|
| 128 bits | 10 | 44 |
| 192 bits | 12 | 52 |
| 256 bits | 14 | 60 |
The final round omits the MixColumns transformation.
SubBytes applies the same non-linear S-box to each byte of the state independently. The AES S-box is a 16×16 table (256 entries) that maps each byte to a substitute byte. It is based on a mathematical operation in GF(2⁸):
The S-box is designed to:
Inverse SubBytes: Uses the inverse S-box.
ShiftRows cyclically shifts the rows of the state to the left by different offsets:
This permutation provides diffusion by moving bytes between columns.
Inverse ShiftRows: Cyclically shifts each row to the right by the same offsets.
MixColumns operates on each column of the state independently. Each column is treated as a polynomial of degree ≤ 3 over GF(2⁸) and multiplied by a fixed polynomial:
a(x) = {03} x³ + {01} x² + {01} x + {02}
modulo (x⁴ + 1). This is equivalent to a matrix multiplication over GF(2⁸):
[ s₀' ] [02 03 01 01] [ s₀ ]
[ s₁' ] = [01 02 03 01] [ s₁ ]
[ s₂' ] [01 01 02 03] [ s₂ ]
[ s₃' ] [03 01 01 02] [ s₃ ]
where all arithmetic is in GF(2⁸).
Inverse MixColumns: Uses the inverse polynomial.
AddRoundKey XORs the state with a round key derived from the master key via the key schedule. Each round key is 16 bytes (128 bits).
The transformation is simply:
state = state ⊕ round_key
This is the only operation that directly mixes the key with the state.
The AES key expansion generates round keys from the master key. The expanded key is an array of 4-byte words (each word is 32 bits).
Algorithm:
Where:
The expanded key provides round keys for each round (including the initial AddRoundKey).
AES decryption applies the inverse of each transformation in reverse order:
For the initial round of decryption, InvMixColumns is not used (corresponding to the final encryption round).
An alternative approach is to apply the inverse transformations to the round keys as well, allowing the use of the same code structure as encryption.
AES has a large security margin: the best attacks reduce the effective key space but still require 2¹²⁶ operations or more. No practical attack exists.
AES is a NIST standard (FIPS 197) and is validated under FIPS 140-2/3 for cryptographic modules. It is also standardized in ISO/IEC 18033-3.
The AES selection process was a landmark in cryptographic history. For the first time, a cryptographic standard was selected through a public, transparent competition. This set a precedent for future standardization efforts (e.g., SHA-3, post-quantum cryptography).
Key events:
Why Rijndael won:
Lessons:
Compute the following in GF(2⁸) using the AES polynomial m(x) = x⁸ + x⁴ + x³ + x + 1:
a. 0x57 ⊕ 0x83 = 0xD4
b. xtime(0x57): 0x57 << 1 = 0xAE, MSB was 0 so no XOR → 0xAE
c. xtime(0x80): 0x80 << 1 = 0x100, MSB was 1 so XOR with 0x1B → 0x00 ⊕ 0x1B = 0x1B
d. 0x57 · 0x02 = xtime(0x57) = 0xAE
Using the AES S-box (provided in the tutorial or lookup table), find the output for the following input bytes:
a. S[0x00] = 0x63 (since 0 has no inverse, the affine transformation gives 0x63)
b. S[0x01] = 0x7C
c. S[0x2F] = 0x15
d. S[0xAB] = 0x62
Given the following state (as a 4×4 array), apply ShiftRows:
[0x00, 0x04, 0x08, 0x0C]
[0x01, 0x05, 0x09, 0x0D]
[0x02, 0x06, 0x0A, 0x0E]
[0x03, 0x07, 0x0B, 0x0F]
After ShiftRows (row 0 shift 0, row 1 shift 1, row 2 shift 2, row 3 shift 3):
[0x00, 0x04, 0x08, 0x0C]
[0x05, 0x09, 0x0D, 0x01]
[0x0A, 0x0E, 0x02, 0x06]
[0x0F, 0x03, 0x07, 0x0B]
For the column [0x87, 0x6E, 0x46, 0xA6] from the tutorial, verify that MixColumns gives [0x4E, 0x70, 0x2D, 0x7D] using GF(2⁸) arithmetic. Show the calculation for s₀' (the first byte).
s₀' = 0x02·0x87 ⊕ 0x03·0x6E ⊕ 0x01·0x46 ⊕ 0x01·0xA6
0x02·0x87 = xtime(0x87) = 0x15 (since 0x87 << 1 = 0x10E, XOR 0x1B = 0x15)
0x03·0x6E = 0x02·0x6E ⊕ 0x6E = xtime(0x6E) ⊕ 0x6E = 0xDC ⊕ 0x6E = 0xB2
0x01·0x46 = 0x46
0x01·0xA6 = 0xA6
s₀' = 0x15 ⊕ 0xB2 ⊕ 0x46 ⊕ 0xA6 = 0x15 ⊕ 0xB2 = 0xA7; 0xA7 ⊕ 0x46 = 0xE1; 0xE1 ⊕ 0xA6 = 0x47
Correction: Let's compute carefully: 0x15 ⊕ 0xB2 = 0xA7; 0xA7 ⊕ 0x46 = 0xE1; 0xE1 ⊕ 0xA6 = 0x47. The tutorial example gave 0x4E; this discrepancy shows the importance of careful GF(2⁸) multiplication.
For AES-128, the first four words of the expanded key are the master key: w[0] = 0x12345678, w[1] = 0x9ABCDEF0, w[2] = 0x0FEDCBA9, w[3] = 0x87654321. Compute w[4] (the first word of the second round key).
Hint: w[4] = w[0] ⊕ SubWord(RotWord(w[3])) ⊕ Rcon[1], where Rcon[1] = 0x01 00 00 00.
w[3] = 0x87654321
RotWord(w[3]) = 0x43218765 (left rotate by 1 byte)
SubWord(0x43218765):
S[0x43] = 0x1A, S[0x21] = 0xFD, S[0x87] = 0x17, S[0x65] = 0x4D
SubWord result = 0x1AFD174D
⊕ Rcon[1] = 0x01000000 → 0x1BFD174D
w[4] = w[0] ⊕ 0x1BFD174D = 0x12345678 ⊕ 0x1BFD174D = 0x09C94135
Research hardware (AES-NI) and software (table-based, bit-sliced) implementations of AES. Write a 500-word report comparing their performance, security considerations (side-channel resistance), and suitability for different applications (e.g., embedded systems, servers, mobile).
Complete answer would discuss AES-NI instructions (Intel/AMD) that provide high-speed hardware acceleration; table-based implementations (fast but vulnerable to cache-timing attacks); and constant-time implementations (secure but slower). It would analyze trade-offs in embedded vs. server environments.
Create a detailed comparison of AES and DES, including key size, block size, structure (Feistel vs. SPN), number of rounds, security strengths, performance, and current status. Write a summary of why AES replaced DES.
Complete answer would include a table showing AES's advantages: larger key sizes (128-256 vs 56), larger block (128 vs 64), SPN structure (better diffusion), faster performance, and strong security against all known attacks. AES replaced DES due to DES's small key and block sizes.
Research how AES is used in a specific application (e.g., TLS, disk encryption, Wi-Fi Protected Access). Describe which AES mode and key size are used, and why.
A complete answer might discuss TLS 1.3 using AES-GCM with 128-bit keys (fast, authenticated), or WPA2 using AES-CCMP (128-bit key), or BitLocker using AES-XTS (128-bit key) for disk encryption. The choice depends on performance requirements, security needs, and standards.
Describe how cache-timing attacks and power analysis attacks can be used to extract an AES key. Explain mitigation techniques used in practice.
Complete answer would explain cache-timing attacks (e.g., using Prime+Probe to observe S-box cache hits) and power analysis (Simple Power Analysis, Differential Power Analysis). Mitigations include constant-time code, table masking, and hardware implementations (AES-NI) that have uniform timing.
Implement AES-128 encryption and decryption in your preferred programming language (or use a library). Test it with NIST test vectors. Report on your implementation, challenges, and performance.
Complete answer would include source code, test results, and a discussion of challenges (e.g., GF(2⁸) multiplication, S-box table generation, key schedule correctness). Observations on performance and code size would also be included.
This tutorial has provided a comprehensive examination of the Advanced Encryption Standard (AES), the world's most widely used symmetric cipher. We traced its history from the NIST competition through its selection and standardization.
We explored the internal structure of AES in detail, starting with the finite field arithmetic in GF(2⁸) that underpins all operations. We examined the state array and the four transformations: SubBytes (non-linear substitution providing confusion), ShiftRows (byte permutation providing diffusion), MixColumns (linear mixing within columns), and AddRoundKey (XOR with the round key).
We covered the key schedule, which generates round keys from the master key, and discussed decryption, which applies the inverse transformations in reverse order. We analyzed AES's security, showing that it is resistant to all known practical attacks, including brute-force, linear, differential, and side-channel attacks. We discussed implementation considerations, including performance and side-channel resistance.
AES represents the state of the art in symmetric encryption and is the standard for secure communication worldwide. Its design principles—simplicity, security margin, and efficiency—are a model for cryptographic algorithm design.
In Tutorial 2.7: Block Cipher Modes of Operation, we will explore how AES (and other block ciphers) are used to encrypt data of arbitrary length. Different modes provide different security properties (confidentiality, authentication, authenticity), and we will examine their strengths and weaknesses in practice.