AES (Advanced Encryption Standard)

Overview

AES (Advanced Encryption Standard) is a symmetric block cipher algorithm that has been the standard for encrypting data since 2001. It was selected by the U.S. National Institute of Standards and Technology (NIST) to replace DES and is now used worldwide for securing sensitive data.

AES operates on fixed-size blocks of data (128 bits) and supports key sizes of 128, 192, or 256 bits. It's fast, secure, and efficient, making it suitable for both software and hardware implementations.

How It Works

AES uses a substitution-permutation network (SPN) structure:

  1. Key Expansion: Derives round keys from the original key
  2. Initial Round: AddRoundKey operation
  3. Main Rounds: Repeated application of:
    • SubBytes - Substitution using S-box
    • ShiftRows - Permutation of rows
    • MixColumns - Mixing of columns
    • AddRoundKey - XOR with round key
  4. Final Round: Same as main rounds but without MixColumns

AES Algorithm


AES_Encrypt(plaintext, key):
    state = plaintext
    expanded_key = KeyExpansion(key)
    
    AddRoundKey(state, expanded_key[0])
    
    for round = 1 to Nr - 1:
        SubBytes(state)
        ShiftRows(state)
        MixColumns(state)
        AddRoundKey(state, expanded_key[round])
    
    SubBytes(state)
    ShiftRows(state)
    AddRoundKey(state, expanded_key[Nr])
    
    return state
                

Implementation

Note: implementing AES yourself is a bad idea — constant-time implementation is genuinely hard, and getting it wrong leaks keys through cache timing. Use a vetted library. The example below uses AES-GCM, an authenticated mode (AEAD), which is what you should reach for by default:


from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os

def aes_encrypt(plaintext, key, associated_data=None):
    """AES-256-GCM: encrypts AND authenticates."""
    nonce = os.urandom(12)                      # 96-bit nonce, NEVER reused with the same key
    aesgcm = AESGCM(key)
    ciphertext = aesgcm.encrypt(nonce, plaintext, associated_data)
    return nonce + ciphertext                   # tag is appended to ciphertext by the library

def aes_decrypt(blob, key, associated_data=None):
    """Raises InvalidTag if the ciphertext was modified. Do not catch and ignore it."""
    nonce, ciphertext = blob[:12], blob[12:]
    aesgcm = AESGCM(key)
    return aesgcm.decrypt(nonce, ciphertext, associated_data)

# Example usage
key = AESGCM.generate_key(bit_length=256)
plaintext = b"Hello, AES Encryption!"          # any length - GCM is a stream mode, no padding
blob = aes_encrypt(plaintext, key)
assert aes_decrypt(blob, key) == plaintext
                

Two things this example fixes that a naive CBC version gets wrong. First, GCM is a stream mode, so plaintext of any length works — CBC requires block-aligned input and would raise ValueError: The length of the provided data is not a multiple of the block length on the 22-byte string above unless you add PKCS#7 padding. Second, and more importantly, GCM authenticates. Raw CBC does not: an attacker who cannot read your ciphertext can still flip bits in it and change the decrypted plaintext in predictable ways, and if your application reveals whether padding was valid, a padding oracle attack recovers the plaintext outright.

The one rule for GCM: never reuse a nonce with the same key. Nonce reuse in GCM is catastrophic — it leaks the XOR of the two plaintexts and the authentication subkey, which lets an attacker forge arbitrary messages. Generate nonces randomly (96 bits gives ample margin) or use a strict counter. If you cannot guarantee nonce uniqueness, use AES-GCM-SIV, which degrades gracefully on reuse.

Specifications

Key Size Block Size Number of Rounds Security Level
128 bits 128 bits 10 High
192 bits 128 bits 12 Very High
256 bits 128 bits 14 Very High

Security

AES is considered highly secure when properly implemented:

  • No known practical attacks against full AES. The best published result is the 2011 biclique attack at roughly 2126.1 for AES-128 — a factor of about four better than brute force, which is to say no threat at all.
  • Related-key attacks exist against the full AES-192 and AES-256 key schedules (Biryukov & Khovratovich, 2009), but they require the attacker to control relationships between keys, which no sane protocol permits.
  • Widely analyzed and tested — AES has had more cryptanalytic attention than any other cipher.
  • Approved for classified information at AES-256 (CNSSP-15). CNSA 2.0 now mandates AES-256 alongside post-quantum algorithms.
  • Implementation is the real risk. The algorithm is sound; the attacks that succeed in practice are side-channel attacks against cache-timing-vulnerable software implementations, and key-management failures.

Best practices:

  • Use an AEAD mode. AES-GCM, AES-GCM-SIV, or ChaCha20-Poly1305. These encrypt and authenticate in one step. Unauthenticated modes (CBC, CTR) are not "less secure options" — they are incomplete, and need a separate MAC applied correctly (encrypt-then-MAC) to be safe. Never use ECB: it encrypts identical plaintext blocks to identical ciphertext blocks, leaving the structure of your data plainly visible.
  • AES-128 is not broken. AES-256 is the sensible default and is required by CNSA 2.0 for classified use, largely for post-quantum margin — Grover's algorithm notionally halves the effective key length, taking AES-256 to a still-comfortable 128 bits. But AES-128 remains secure against classical attack.
  • Generate keys with a cryptographically secure RNG (os.urandom, secrets), never random.
  • Respect key wear-out limits. A single AES-GCM key should not encrypt more than about 232 messages.
  • Use hardware AES (AES-NI) where available — it is both faster and constant-time, which naive software S-box implementations are not.

Applications

  • Data Encryption: File encryption, database encryption
  • Network Security: SSL/TLS, VPN protocols
  • Disk Encryption: Full disk encryption systems
  • Wireless Security: WPA2, WPA3
  • Government Use: Classified information protection

Related Algorithms

Explore other encryption algorithms: