Attacks & Pitfalls
Common Mistakes
Nonce reuse, ECB, home-rolled crypto, and other recurring failures.
Most cryptographic vulnerabilities are not clever breaks of hard math. They are the same handful of implementation mistakes repeated across decades and codebases: a reused nonce, the wrong mode, a home-rolled cipher, a comparison that leaks timing. Learning this catalog with the real CVEs attached is the fastest way to develop the instinct that flags dangerous code on sight.
Why This Matters
You will review far more crypto code than you write, and the bugs that matter are rarely subtle to someone who knows the patterns. Recognizing “this uses ECB,” “this nonce is a counter that resets,” or “this rolls its own MAC” turns a code review from a rubber stamp into a real defense. Every item below has shipped in production somewhere and cost real money.
A Tour of the Top Failures
| Mistake | Why it breaks | Real-world case |
|---|---|---|
| ECB mode | Identical plaintext blocks map to identical ciphertext, leaking structure | Adobe 2013 password dump revealed patterns |
| Nonce/IV reuse in GCM | Two messages under one nonce leak the auth key, enabling forgery | Documented in the AES-GCM nonce-reuse literature |
| Predictable randomness | Keys become guessable | Debian OpenSSL 2008 crippled the PRNG; keys brute-forceable |
| Home-rolled crypto | Subtle flaws no one catches | Countless custom XOR “encryption” schemes |
| No integrity (unauthenticated CBC) | Ciphertext is malleable; padding oracles | See sibling Padding Oracle page |
| Non-constant-time compare | Timing reveals secret byte by byte | See sibling Side Channels page |
| Static IVs | Same as nonce reuse for CBC/CTR | Hardcoded IVs in mobile apps (many CVEs) |
| MD5/SHA-1 for signatures | Collisions forge documents | Flame malware forged a Microsoft cert via MD5 |
Library Misuse: Bad Defaults and Good Defaults
Libraries differ enormously in how easy they make the wrong thing. The single best defense is choosing a library whose defaults are safe and whose API is hard to misuse.
| Library / API | Default behavior | Verdict |
|---|---|---|
Low-level OpenSSL EVP with ECB or manual IV | You must get mode, IV, and auth right yourself | Easy to misuse |
Python cryptography Fernet | AES-CBC plus HMAC, random IV, versioned | Safe default |
libsodium / NaCl crypto_secretbox | Authenticated, nonce required explicitly | Hard to misuse |
Go crypto/cipher GCM | AEAD, but you supply the nonce | Safe if nonce is unique |
Java Cipher.getInstance("AES") | Silently defaults to ECB | Dangerous default |
The lesson: AES alone is not a choice, it is a trap. Cipher.getInstance("AES") in Java expands to AES/ECB/PKCS5Padding, and countless apps encrypt with ECB without realizing it.
Spotting ECB in Practice
You can often detect ECB just by looking for repeated ciphertext blocks, no key required.
cd ~/crypto-lab
head -c 64 /dev/zero > zeros.bin
openssl enc -aes-128-ecb -K 000102030405060708090a0b0c0d0e0f -in zeros.bin -out out.bin
xxd out.bin | awk '{print $2, $3}' | sort | uniq -c
Expected output:
4 66e94bd4 ef8a2c3b
Four identical blocks of ciphertext from four identical blocks of input: the signature of ECB. A proper mode (CBC with a random IV, or better, GCM) would produce four different blocks.
Code-Review Checklist for Crypto Usage
When reviewing code that touches cryptography, check each of these:
- Is an authenticated mode (AEAD: GCM, ChaCha20-Poly1305) used, not raw CBC/CTR/ECB?
- Is every nonce/IV unique per key, and generated from a CSPRNG or a guaranteed-unique counter?
- Does randomness come from a cryptographically secure source (
os.urandom,crypto/rand,getrandom)? - Are secrets compared in constant time (
hmac.compare_digest,subtle.ConstantTimeCompare)? - Are hash functions modern (SHA-256+), never MD5 or SHA-1 for security?
- Is there any custom cipher, mode, or MAC construction? If so, reject it.
- Are keys derived with a proper KDF (HKDF, Argon2, scrypt), not raw passwords?
Practical Guidance
- Default to a high-level, misuse-resistant library (libsodium,
cryptographyFernet) instead of assembling primitives yourself. - Never write
getInstance("AES")or any API that silently selects ECB; always specify an authenticated mode explicitly. - Generate nonces and IVs from a CSPRNG and never reuse one under the same key.
- Reject any home-rolled cryptographic construction in review, no matter how clever it looks.
- Run the checklist above on every change that touches encryption, signing, or key handling, and cross-reference the sibling Padding Oracle and Side Channels pages for the attacks behind two of its items.