Claude Code: Finding Cryptographic Weaknesses in Legacy Code
The Audit Workflow
To actually get value out of this, you can't just paste a file and ask "is this secure?" You need a specific AI workflow that forces the model to act like a security researcher rather than a generic assistant. Here is the step-by-step process I've been using for this kind of deep dive.
1. Isolate the Primitive: Extract the specific function handling the encryption, hashing, or key derivation. Don't feed it the whole project or it will get distracted by UI logic.
2. Context Injection: Tell the model the expected security level (e.g., "This is for a financial transaction system") and the specific threat model you are worried about (e.g., "Known Plaintext Attack").
3. The "Devil's Advocate" Prompt: Force it to find a flaw. Instead of asking if it's secure, ask: "If you were an attacker trying to break this specific implementation, where is the most likely point of failure?"
Common Weaknesses Spotted
In my recent tests, Claude was particularly good at flagging these specific issues that often slip through manual peer reviews:
- IV Reuse: Spotting where a Static Initialization Vector is used across multiple encryption calls, which is a classic disaster for AES-GCM.
- Weak KDFs: Identifying the use of PBKDF2 with too few iterations or, worse, a raw SHA-256 hash for password storage.
- Padding Oracle Vulnerabilities: Detecting improper handling of PKCS#7 padding in legacy Java or C# apps.
- Hardcoded Secrets: Finding those "temporary" keys that somehow made it into the production branch.
Practical Example: Spotting a Weak Salt
I ran a snippet of a custom hashing function through it, and while the code compiled and worked perfectly, Claude caught a critical flaw in how the salt was generated.
import hashlib
import os
# The flaw: using a predictable seed or a too-short salt
def insecure_hash(password):
salt = b'fixed_salt_123' # Claude flagged this as a critical weakness
return hashlib.sha256(salt + password.encode()).hexdigest()The model didn't just say it was "bad"; it explained that a fixed salt allows for rainbow table attacks across the entire user base. It then suggested a deployment pattern using os.urandom(16) and storing the salt alongside the hash.
For anyone doing a hands-on guide for security auditing, using an LLM agent as a first-pass filter saves hours of manual tracing. It doesn't replace a professional audit, but it catches the "low hanging fruit" and allows the human dev to focus on the complex architectural flaws.