Block Cipher Modes
debt(d5/e3/b3/t9)
Closest to 'specialist tool catches it' (d5), because detection_hints lists semgrep and psalm as tools, and the code_pattern shows specific detectable patterns (ECB mode, CBC without HMAC, IV reuse) — these require configured specialist rules rather than a default linter or compiler, placing them squarely at d5.
Closest to 'simple parameterised fix' (e3), because quick_fix says to swap to AES-256-GCM in one call to openssl_encrypt with different parameters. The fix is a mode replacement that may also require adding authentication handling (IV generation, tag verification), touching a small number of call sites within one component rather than a single-line swap or a cross-cutting refactor.
Closest to 'localised tax' (b3), because applies_to scopes this to web and CLI contexts and the encryption choice is typically localised to a crypto/service layer. Once corrected to GCM, the rest of the codebase is unaffected; however the wrong choice does impose ongoing risk in that layer, slightly above b1 but not reaching b5 since it rarely bleeds into every work stream.
Closest to 'catastrophic trap' (t9), because the misconception field states explicitly that 'AES is AES regardless of mode' — a competent developer who knows AES naturally assumes mode is a minor implementation detail, while in reality ECB leaks structure completely and IV reuse in GCM reveals both plaintexts. The 'obvious' choice (ECB or CBC) is always cryptographically wrong for structured data, matching the t9 anchor perfectly.
Also Known As
TL;DR
Explanation
Block ciphers encrypt fixed-size blocks. Modes define how blocks relate: ECB (each block encrypted independently — identical plaintext blocks produce identical ciphertext, leaking patterns), CBC (each block XORed with previous ciphertext — requires padding and a separate MAC for integrity), CTR (turns block cipher into stream cipher — no padding, but no authentication), GCM (CTR mode + GHASH authentication — authenticated encryption, no separate MAC needed, parallelisable). AES-256-GCM is the correct choice for new implementations. Nonces/IVs must be unique per encryption.
Watch Out
Common Misconception
Why It Matters
Common Mistakes
- AES-ECB for any structured data — identical 16-byte blocks produce identical ciphertext, leaking structure.
- CBC without MAC (encrypt-then-MAC) — CBC is malleable; an attacker can modify ciphertext without detection.
- Reusing an IV with the same key in GCM — catastrophic; two ciphertexts XOR to reveal both plaintexts.
- Not authenticating the associated data in GCM — headers/metadata can be tampered without invalidating the tag.
Code Examples
// AES-ECB — insecure:
$encrypted = openssl_encrypt($data, 'AES-256-ECB', $key);
// Identical 16-byte blocks encrypt identically
// 'aaaaaaaaaaaaaaaa' encrypts to the same ciphertext every time
// CBC without authentication:
$iv = random_bytes(16);
$encrypted = openssl_encrypt($data, 'AES-256-CBC', $key, 0, $iv);
// No MAC — ciphertext can be silently tampered
// AES-256-GCM — authenticated encryption:
$iv = random_bytes(12); // 96-bit nonce for GCM
$tag = '';
$ciphertext = openssl_encrypt(
$data, 'AES-256-GCM', $key, OPENSSL_RAW_DATA, $iv, $tag,
$additionalData // Authenticated but not encrypted (e.g. sender ID)
);
$stored = base64_encode($iv . $tag . $ciphertext);
// Decryption verifies tag automatically — tampered data rejected