Broken today, no quantum computer needed.
MD5 on a password, ECB mode or a disabled certificate check can be exploited now. NightVision finds these choices in your code and settings, rates each one by the role it plays, and names what to use instead.
Weak cryptography is a cryptographic choice an attacker can exploit with today's computers: a broken algorithm such as MD5, DES or RC4, a deprecated one such as 3DES or TLS 1.0, a sound primitive used unsoundly, such as AES in ECB mode or an IV written into the source, or verification switched off. NightVision sorts these into five classes and rates each finding by what the algorithm does where it is used, so a cache key does not rank with a password.
Five ways cryptography goes wrong before quantum
The same pass that finds quantum-vulnerable choices reports these. Severity follows the risk: what an attacker can do with the choice today.
| Class | What it means | Examples | Severity |
|---|---|---|---|
| Broken | Practical attacks are known. | MD5 and SHA-1 digests and signatures, DES, RC4, SSL 2.0 and 3.0, JWT alg of none, plaintext or fast-hash password storage, NULL and export cipher suites, RSA below 1024 bits |
High A digest is high only when it hashes a secret, low otherwise |
| Deprecated | Below current minimums: NIST SP 800-131A disallows it, or the IETF has retired it. | 3DES, RC2, Blowfish, CAST5, IDEA, RSA and DH below 2048 bits, curves below 224 bits, DSA, TLS 1.0 and 1.1, HMAC-MD5, HMAC-SHA-1 and SHA-224 | MediumLow |
| Misuse | A sound primitive used unsoundly. | ECB mode, an IV written in the source, RSA PKCS #1 v1.5 encryption, fewer than 10,000 PBKDF2 iterations, certificate, host name or token signature verification turned off, OpenSSL security level below 2 | HighMedium |
| Unvalidated implementation | A standard algorithm written by hand in the tree instead of taken from a validated library. | A hand-written MD5, an AES S-box in the application's own code | Medium |
| Unapproved library | A cryptography library outside the approved set. An inventory item to review, not a fault. | CryptoJS, PyCrypto, pyDes, mcrypt, phpseclib 1.x | Info |
Same algorithm, different verdict
"SHA-1 found" is not something anyone can act on. What matters is what the algorithm does at that line, so NightVision assesses each choice where a call consumes it, by the role it plays there.
hashlib.sha1(password)
High when the call hashes a password, secret or token. Low for a cache key or a file name. Medium as the hash of a signature in code.
hmac.new(key, msg, hashlib.sha1)
HMAC-SHA-1 has no practical break, but it is below current minimums and has a NIST retirement date.
padding.OAEP(algorithm=hashes.SHA1(), ...)
Inside RSA-OAEP padding, SHA-1 raises nothing.
key.encrypt(data, padding.PKCS1v15())
RSA PKCS #1 v1.5 encryption is weak. Use RSAES-OAEP.
key.sign(data, padding.PKCS1v15(), hashes.SHA256())
The same padding is sound for a signature, so it is not reported where it is built.
Password schemes get the same treatment: in Django's PASSWORD_HASHERS or a passlib context, the finding records whether a weak scheme hashes new passwords or is only kept to verify old ones.
A digest is high only when it hashes a secret
Most MD5 and SHA-1 calls in real applications key a cache, name a file or deduplicate records. Rating every one of them high buries the one that hashes a password.
NightVision raises a broken digest to high only when the call names the data it hashes as a password, a secret or a token: an argument such as password, user_pwd, clientSecret, apiKey or token_data. The finding records input as sensitive. Any other broken digest is low.
Hashing a password with any fast hash is a misuse, but only a broken one (MD2, MD4, MD5 or SHA-1) is raised to high for it. The judgment reads the names at the call, so md5() followed later by update(password) is rated low.
hashlib.md5(password)hashlib.sha1(token_data)hashlib.md5(cache_key)hashlib.md5(data, usedforsecurity=False)hashlib.sha224(password)What it flags, and what to write instead
Each finding carries its remediation. A sample of what the Python rules catch:
DES.new(key, DES.MODE_CBC, iv)brokenInstead: AES in an authenticated mode such as GCM, or ChaCha20-Poly1305. The same holds for RC4 and 3DES.
Cipher(algorithms.AES(key), modes.ECB())misuseInstead: an authenticated mode such as AES-GCM. ECB encrypts equal blocks to equal ciphertext.
modes.CBC(b"0123456789abcdef")misuseInstead: a fresh IV for every message, not one written in the source.
hashlib.pbkdf2_hmac("sha256", pw, salt, 1000)misuseInstead: a password hash at OWASP's current cost. Under 10,000 PBKDF2 iterations is flagged.
requests.get(url, verify=False)misuseInstead: leave certificate verification on. httpx and aiohttp calls are read too, and so is check_hostname = False on an ssl context.
jwt.decode(t, key, options={"verify_signature": False})misuseInstead: verify the token's signature, with an explicit list of allowed algorithms.
jwt.encode(claims, key, algorithm="none")brokenInstead: sign every token. An unsigned JWT can be forged by anyone.
ssl.SSLContext(ssl.PROTOCOL_TLSv1)deprecatedInstead: TLS 1.2 or later. TLS 1.0 and 1.1 in nginx, Apache and OpenSSL configuration are flagged too.
What it leaves out, on purpose
A report that flags every hash call gets ignored. These are not reported, so what remains needs a change:
- AES and ChaCha20 with 128-bit keys or more, SHA-256 and above, and HMAC-SHA-256.
- A digest called with
usedforsecurity=False, which declares it is not a security use. - A choice the source does not fix: one read from the environment with no default, from a file, or from a vault.
- Apache's
all, which admits whatever the linked OpenSSL admits rather than a choice the file makes.
Lines a developer marked for another tool with nosec, nosemgrep or a flake8-bandit noqa are still reported, with the marker named, so you can hide accepted findings deliberately instead of losing them.
Code and framework settings are read in Python today: hashlib, hmac, pyca/cryptography, PyCryptodome and PyCrypto, ssl, requests, httpx and aiohttp verification, PyJWT, python-jose, jwcrypto, passlib, Django, Flask-JWT-Extended and Flask-Security. Committed keys, TLS configuration, dependency manifests and hand-written algorithms are read in any language; see keys, certificates and TLS.
In the NightVision CLI, beside your API spec
Add --weak-crypto to nightvision openapi extract and the report is written beside the API spec that source intelligence generates. A default run uploads the spec and the report to NightVision, and --no-upload sends nothing. Source code is never uploaded, and no language model reads it. Viewing and tracking these findings in the NightVision platform is in development.
Questions about weak cryptography.
What is weak cryptography?
A cryptographic choice an attacker can exploit with today's computers: a broken or deprecated algorithm, a sound primitive used unsoundly, a standard algorithm written by hand, or verification turned off. It needs fixing now, whatever the quantum timeline.
Is SHA-1 always flagged?
No. SHA-1 is broken as a digest or a signature hash, deprecated as an HMAC hash, and not reported as the hash inside RSA-OAEP. NightVision rates it by the role it plays where it is used.
Why is my MD5 finding rated low?
A broken digest is rated high only when the call names the data it hashes as a password, a secret or a token. Most MD5 and SHA-1 digests key a cache, name a file or deduplicate records, so those are rated low.
Does NightVision flag AES or SHA-256?
No. AES and ChaCha20 with 128-bit keys or more, and SHA-256 and above, are not reported. AES in ECB mode, or with an IV written in the source, is reported as a misuse.
Which languages are covered?
Code and framework settings are analyzed in Python today. Committed keys, certificates, TLS configuration, dependency manifests and hand-written algorithms are read in any language.
Where does this run today?
It runs in the NightVision CLI today: add the --weak-crypto flag to nightvision openapi extract and the report is written beside the API spec that source intelligence generates. The --no-upload flag sends nothing to NightVision. Viewing and tracking these findings in the NightVision platform is in development.
Fix what is broken now.
Find the weak cryptography in your code and committed files, rated by what it protects, with what to use instead. Then plan for what quantum breaks.