Prerequisites
- Target system, dependencies and environment configured.
Usage
Purpose
Almost nobody breaks crypto by attacking the math. They break it because the code used ECB, reused a nonce, hashed passwords with SHA-256, or seeded a "random" token with the current time. This skill is a review pass for the recognisable misuse patterns — you don't need to be a cryptographer to catch the ones that actually get exploited.
When to use it
Any change touching encryption, password storage, token/session generation, signing, or "generate a secret." Also worth a periodic sweep — crypto misuse tends to get copied from an old file into a new one.
The patterns, worst first
- Passwords through a fast hash. MD5, SHA-1, SHA-256, SHA-512 for password storage. Fast is the problem — it makes cracking cheap. Password storage wants a slow, salted KDF: bcrypt, scrypt, Argon2id, or PBKDF2 with a high iteration count. (There's a dedicated skill for this in domain 11; here you just need to spot the fast hash and stop.)
- ECB mode.
AES/ECB/..., or any encryption where identical plaintext blocks produce identical ciphertext. It leaks structure. Authenticated modes (GCM, or ChaCha20-Poly1305) are the default answer.
- Static or reused IV/nonce. A hardcoded IV, an all-zero IV, or a counter that resets. With GCM, nonce reuse under the same key is catastrophic — it can leak the auth key. Look for the IV being a constant or derived deterministically.
Math.random() / rand() for anything security-relevant. Tokens, password-reset codes, session ids, salts. These PRNGs are predictable. Security randomness needs a CSPRNG: SecureRandom, crypto.randomBytes, secrets, /dev/urandom.
- Hardcoded keys / IVs / salts. A key in source is not a key. (Overlaps with the secrets-in-code skill — flag from both angles.)
- Encrypt-without-authenticate. CBC without a MAC invites padding-oracle and bit-flipping attacks. Prefer AEAD; if you see raw CBC, ask where the integrity check is.
- Home-grown crypto. Custom "encryption," XOR obfuscation dressed up as security, a bespoke signature scheme. Treat any hand-rolled primitive as broken until a real one replaces it.
- Weak or skipped verification. Signature/JWT verification that catches the exception and continues,
verify=False, accepting alg: none. (JWT specifics live in domain 04.)
Procedure
- Grep the primitives and modes (cheatsheet).
- Sort hits by blast radius: password hashing and key handling first, then modes/IVs, then randomness.
- For each, name the property that should hold (confidentiality, integrity, unpredictability, slow-to-crack) and check the code actually provides it.
- Follow keys and IVs to their origin — constant, config, derived, or a KDF? Constants are findings.
- Don't try to "fix" a hand-rolled scheme by patching it. The finding is replace it with a standard library primitive.
Cheatsheet
rg -n 'MD5|SHA-?1|MessageDigest\.getInstance\("(MD5|SHA-1|SHA-256)"'
rg -n 'AES/ECB|Cipher\.getInstance\("AES"\)|DES|RC4|/CBC/'
rg -n 'Math\.random|new Random\(|rand\(\)|mt_rand|random\.random\('
rg -n 'IvParameterSpec\(|SecretKeySpec\(|byte\[\] *(key|iv) *='
rg -n 'verify=False|alg.{0,3}none|InsecureRequestWarning|checkServerIdentity'
Reading it
- A fast hash on a password → finding, regardless of salt. Salt doesn't fix speed.
- The same MD5 on a file checksum or cache key → fine. Judge by what it protects, not the algorithm name alone.
SecureRandom seeded manually (new SecureRandom(seed) with a known seed) → back to predictable; flag it.
- GCM with a nonce that isn't unique per message → critical; note it specifically.
- A
catch around signature verification that logs and proceeds → the verification is theatre.
The fix
Reach for the platform's vetted library and its safe defaults: Argon2id/bcrypt for passwords, AES-GCM or ChaCha20-Poly1305 for encryption, a CSPRNG for anything unpredictable, keys from a secrets manager or KMS. The reviewer's rule of thumb: if the code chooses a mode, IV, or hash by hand, that's where the bug is — safe-by-default APIs don't make you choose.
Pitfalls
- Algorithm-name matching without context. MD5 for a non-security checksum isn't a bug. Ask what property it's guarding.
- Accepting a salt as sufficient for a fast hash. It isn't — the KDF's slowness is the point.
- Missing the IV. People check the cipher and forget the nonce, which is where GCM actually dies.
- Patching hand-rolled crypto. Replace, don't repair.
References
- OWASP Cryptographic Storage Cheat Sheet
- CWE-327 (broken/risky algorithm), CWE-329 (missing/predictable IV), CWE-338 (weak PRNG), CWE-916 (weak password hash)
Inputs
- Relevant source code, logs, network traces, or system specifications.
Outputs
- Analysis findings, security audit report, or generated code artifacts.
1---2name: crypto-misuse-review3description: Use when reviewing code that encrypts, hashes, signs, or generates randomness — finding weak algorithms, misused primitives, and hand-rolled crypto before they ship.4---5678## Prerequisites9- Target system, dependencies and environment configured.1011## Usage12### Purpose1314Almost nobody breaks crypto by attacking the math. They break it because the code used ECB, reused a nonce, hashed passwords with SHA-256, or seeded a "random" token with the current time. This skill is a review pass for the recognisable misuse patterns — you don't need to be a cryptographer to catch the ones that actually get exploited.1516### When to use it1718Any change touching encryption, password storage, token/session generation, signing, or "generate a secret." Also worth a periodic sweep — crypto misuse tends to get copied from an old file into a new one.1920### The patterns, worst first2122- **Passwords through a fast hash.** MD5, SHA-1, SHA-256, SHA-512 for password storage. Fast is the problem — it makes cracking cheap. Password storage wants a slow, salted KDF: bcrypt, scrypt, Argon2id, or PBKDF2 with a high iteration count. (There's a dedicated skill for this in domain 11; here you just need to spot the fast hash and stop.)23- **ECB mode.** `AES/ECB/...`, or any encryption where identical plaintext blocks produce identical ciphertext. It leaks structure. Authenticated modes (GCM, or ChaCha20-Poly1305) are the default answer.24- **Static or reused IV/nonce.** A hardcoded IV, an all-zero IV, or a counter that resets. With GCM, nonce reuse under the same key is catastrophic — it can leak the auth key. Look for the IV being a constant or derived deterministically.25- **`Math.random()` / `rand()` for anything security-relevant.** Tokens, password-reset codes, session ids, salts. These PRNGs are predictable. Security randomness needs a CSPRNG: `SecureRandom`, `crypto.randomBytes`, `secrets`, `/dev/urandom`.26- **Hardcoded keys / IVs / salts.** A key in source is not a key. (Overlaps with the secrets-in-code skill — flag from both angles.)27- **Encrypt-without-authenticate.** CBC without a MAC invites padding-oracle and bit-flipping attacks. Prefer AEAD; if you see raw CBC, ask where the integrity check is.28- **Home-grown crypto.** Custom "encryption," XOR obfuscation dressed up as security, a bespoke signature scheme. Treat any hand-rolled primitive as broken until a real one replaces it.29- **Weak or skipped verification.** Signature/JWT verification that catches the exception and continues, `verify=False`, accepting `alg: none`. (JWT specifics live in domain 04.)3031### Procedure32331. Grep the primitives and modes (cheatsheet).342. Sort hits by blast radius: password hashing and key handling first, then modes/IVs, then randomness.353. For each, name the property that should hold (confidentiality, integrity, unpredictability, slow-to-crack) and check the code actually provides it.364. Follow keys and IVs to their origin — constant, config, derived, or a KDF? Constants are findings.375. Don't try to "fix" a hand-rolled scheme by patching it. The finding is *replace it with a standard library primitive.*3839### Cheatsheet4041```bash42rg -n 'MD5|SHA-?1|MessageDigest\.getInstance\("(MD5|SHA-1|SHA-256)"'43rg -n 'AES/ECB|Cipher\.getInstance\("AES"\)|DES|RC4|/CBC/'44rg -n 'Math\.random|new Random\(|rand\(\)|mt_rand|random\.random\('45rg -n 'IvParameterSpec\(|SecretKeySpec\(|byte\[\] *(key|iv) *='46rg -n 'verify=False|alg.{0,3}none|InsecureRequestWarning|checkServerIdentity'47```4849### Reading it5051- **A fast hash on a password** → finding, regardless of salt. Salt doesn't fix speed.52- **The same MD5 on a file checksum or cache key** → fine. Judge by *what it protects*, not the algorithm name alone.53- **`SecureRandom` seeded manually** (`new SecureRandom(seed)` with a known seed) → back to predictable; flag it.54- **GCM with a nonce that isn't unique per message** → critical; note it specifically.55- **A `catch` around signature verification that logs and proceeds** → the verification is theatre.5657### The fix5859Reach for the platform's vetted library and its safe defaults: Argon2id/bcrypt for passwords, AES-GCM or ChaCha20-Poly1305 for encryption, a CSPRNG for anything unpredictable, keys from a secrets manager or KMS. The reviewer's rule of thumb: if the code *chooses* a mode, IV, or hash by hand, that's where the bug is — safe-by-default APIs don't make you choose.6061### Pitfalls6263- **Algorithm-name matching without context.** MD5 for a non-security checksum isn't a bug. Ask what property it's guarding.64- **Accepting a salt as sufficient for a fast hash.** It isn't — the KDF's slowness is the point.65- **Missing the IV.** People check the cipher and forget the nonce, which is where GCM actually dies.66- **Patching hand-rolled crypto.** Replace, don't repair.6768### References6970- OWASP Cryptographic Storage Cheat Sheet71- CWE-327 (broken/risky algorithm), CWE-329 (missing/predictable IV), CWE-338 (weak PRNG), CWE-916 (weak password hash)7273## Inputs74- Relevant source code, logs, network traces, or system specifications.7576## Outputs77- Analysis findings, security audit report, or generated code artifacts.