Cryptography Common Mistakes
debt(d5/e5/b7/t7)
Closest to 'specialist tool catches' (d5). Semgrep and Psalm (from detection_hints.tools) can detect patterns like AES-ECB mode, static IV constants, and openssl_encrypt without MAC through static analysis rules. However, these require specific rulesets configured for cryptographic anti-patterns rather than default linting.
Closest to 'touches multiple files / significant refactor' (e5). While the quick_fix suggests AES-256-GCM avoids common mistakes, retrofitting existing encryption throughout a codebase requires updating all encryption/decryption call sites, migrating stored ciphertext, and ensuring consistent authenticated encryption across the system.
Closest to 'strong gravitational pull' (b7). Cryptographic choices in applies_to contexts (web, cli) become load-bearing infrastructure. Password hashing, token generation, and data encryption are used system-wide; a wrong choice (e.g., SHA-256 for passwords instead of Argon2id) shapes how authentication and data protection work everywhere, requiring coordinated migration to fix.
Closest to 'serious trap' (t7). The misconception explicitly states that developers believe 'openssl_encrypt is always sufficient' when encryption without authentication allows ciphertext modification. Using == for MAC comparison seems correct but enables timing attacks. These contradict how similar concepts work elsewhere (comparison operators, basic encryption) and the 'obvious' approach fails silently.
Also Known As
TL;DR
Explanation
Common mistakes: (1) Rolling your own crypto — use battle-tested libraries only. (2) Reusing IV/nonce in GCM — catastrophically breaks confidentiality and authentication. (3) ECB mode — identical plaintext blocks produce identical ciphertext, leaking patterns. (4) Timing-vulnerable comparison — use hash_equals() not ==. (5) SHA-256 for passwords — fast algorithm, GPU-crackable; use Argon2id. (6) No authenticated encryption — AES-CBC without MAC allows ciphertext tampering. (7) Trusting user-provided algorithm — JWT alg:none, algorithm confusion attacks.
Common Misconception
Why It Matters
Common Mistakes
- AES-CBC without MAC — ciphertext is malleable
- IV/nonce reuse in GCM — recovering the auth key
- SHA-256 for passwords — bcrypt/Argon2id is required
- == for comparing MACs/tokens — timing attack enables brute-force
Code Examples
// Multiple critical mistakes:
$key = 'secret'; // Short, non-derived key
$iv = str_repeat('0', 16); // Static IV — reused every time!
$enc = openssl_encrypt($data, 'AES-128-ECB', $key); // ECB mode!
// No authentication — ciphertext tamperable
if ($provided === $expected) { } // Timing vulnerable
// Correct authenticated encryption:
$key = random_bytes(32); // 256-bit key from CSPRNG
$iv = random_bytes(12); // Random 96-bit nonce per message
$tag = '';
$enc = openssl_encrypt(
$data, 'AES-256-GCM', $key, OPENSSL_RAW_DATA, $iv, $tag
);
// Constant-time comparison:
if (!hash_equals($expected, $provided)) {
throw new SecurityException('Authentication failed');
}