Block weak ciphers, predictable RNG, undersized keys, fast-hash password storage, nonce reuse, and non-constant-time comparison. Use when generating code that hashes, encrypts, or signs, code that compares secrets, MACs, or tokens, or config for key sizes and randomness.
Scanned 9/6/2026
Install to Claude Code
npx -y skills add ShieldNet-360/secure-vibe --skill crypto-misuse --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Crypto Misuse?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/shieldnet-360-crypto-misuse-98e3cae2)More formats (shields.io, HTML) on the badges page.
---
id: crypto-misuse
version: "1.1.0"
title: "Cryptographic Misuse"
description: "Block weak ciphers, predictable RNG, undersized keys, fast-hash password storage, nonce reuse, and non-constant-time comparison. Use when generating code that hashes, encrypts, or signs, code that compares secrets, MACs, or tokens, or config for key sizes and randomness."
category: prevention
severity: critical
applies_to:
- "when generating code that hashes / encrypts / signs"
- "when generating code that compares secrets / MACs / tokens"
- "when choosing an algorithm, key size, or RNG"
languages: ["*"]
token_budget:
minimal: 1700
compact: 2300
full: 3400
rules_path: "rules/"
related_skills: ["auth-security", "protocol-security", "secret-detection"]
last_updated: "2026-08-12"
sources:
- "OWASP Password Storage Cheat Sheet"
- "OWASP Cryptographic Storage Cheat Sheet"
- "NIST SP 800-131A (current revision)"
- "NIST SP 800-57 Part 1 (current revision)"
- "CWE-327, CWE-338, CWE-916, CWE-208"
---
# Cryptographic Misuse
## Rules (for AI agents)
### ALWAYS
- Use a maintained, widely reviewed cryptographic API — the platform's own (Node
`crypto`, Java JCE, .NET `System.Security.Cryptography`, Go `crypto/*`) or a
reputable third-party one (PyCA `cryptography`, `golang.org/x/crypto`, Bouncy
Castle). Prefer high-level, misuse-resistant APIs over assembling low-level
primitives yourself. In Python, `from Crypto…` resolves to either the abandoned
`pycrypto` or its maintained fork `pycryptodome` depending on what is installed —
the import line is identical, so depend on `pycryptodome` explicitly.
- Use a cryptographically secure RNG for anything security-relevant: Python
`secrets.token_bytes` / `secrets.token_urlsafe`, JS `crypto.getRandomValues` /
`crypto.randomBytes`, Go `crypto/rand.Read`, Java `SecureRandom`.
- Hash passwords with a password-specific KDF and a unique random salt per password.
Prefer Argon2id; scrypt where appropriate; bcrypt for legacy compatibility;
PBKDF2-HMAC-SHA-256 where FIPS-140 compliance is required. Take minimum parameters
from the current [OWASP Password Storage Cheat
Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html),
then benchmark on production hardware and choose the highest cost that still meets
the application's authentication latency and availability budget. The cost is meant
to be raised over time as hardware gets cheaper — it is not a constant to copy once.
- Account for bcrypt's 72-byte input limit: it silently truncates, so a long
passphrase and its 72-byte prefix hash identically. If bcrypt must take unbounded
input, pre-hash with SHA-256 and pass the digest **base64-encoded**, never as raw
bytes — a raw digest can contain a NUL byte, which truncates the input again.
- Encrypt with a vetted AEAD: AES-GCM or ChaCha20-Poly1305, or AES-GCM-SIV where
nonce-misuse resistance is specifically useful and the platform ships a reviewed
implementation. Absent a stated key-size requirement, AES-256-GCM or
ChaCha20-Poly1305 is a safe default — AES-128-GCM is not a finding.
- Follow the selected AEAD's nonce requirements. For AES-GCM and ChaCha20-Poly1305 the
requirement is **uniqueness** under a given key, not randomness. A random 96-bit
nonce is one strategy and carries a birthday bound; a counter-based nonce is often
the stronger choice for high-volume encryption under one key. Do not assume
nonce-misuse resistance unless the construction explicitly provides it.
- Compare MACs, authentication tokens, and other secret authenticators with the
platform's constant-time helper: Python `hmac.compare_digest`, Node
`crypto.timingSafeEqual`, Go `crypto/subtle.ConstantTimeCompare`, Java
`MessageDigest.isEqual`, .NET `CryptographicOperations.FixedTimeEquals`. Node's
helper throws when the buffers differ in length, so compare fixed-length digests
rather than raw user input. For digital signatures, call the library's verification
API instead of comparing signature bytes yourself. A constant-time comparison does
not make the surrounding code constant-time.
- Select asymmetric algorithms and key sizes from current authoritative guidance
rather than remembered constants. Prefer a modern platform-supported scheme
(Ed25519, X25519, ECDSA P-256 or P-384); where RSA is required, enforce the current
NIST SP 800-57 Part 1 minimum modulus. Key-size floors only move upward, so a
remembered figure is one that has already expired.
- Obtain production keys from the platform's key-management boundary — see
`secret-detection` for what counts as an embedded credential. What this skill owns
is what comes after: version every key (carry a key id in the ciphertext envelope)
so rotation does not strand data encrypted under the previous key, and derive
per-purpose subkeys with a KDF instead of reusing one key across contexts.
- Consult `protocol-security` for anything on the wire — TLS versions and cipher
suites, mTLS, certificate validation, gRPC channel credentials. It owns the
transport; this skill owns the primitive.
### NEVER
- Use MD5 or SHA-1 for signatures, certificates, password storage, or message
authentication.
- Use DES, 3DES, RC4, or Blowfish in new code.
- Use ECB mode. It leaks plaintext structure no matter how strong the key is.
- For a new design, assemble encryption yourself from an unauthenticated mode (CBC,
CTR) plus a separately implemented MAC while a vetted AEAD is available.
- Store passwords with a fast hash (`sha256(password)`, MD5, SHA-1) or with a shared
or fixed salt.
- Use JavaScript `Math.random()`, Python `random` (its `random.SystemRandom` is the
exception), C `rand()`, or Go `math/rand` — `math/rand/v2` included — for tokens,
IDs, nonces, keys, or passwords. Auto-seeding does not make a PRNG a CSPRNG.
- Hardcode a production key, or reuse a nonce / IV where the construction requires
uniqueness. A protocol- or KDF-defined salt that is public by design (HKDF's `salt`
parameter) is a different thing and may legitimately be fixed.
- Compare a MAC, secret token, password-derived value, or other secret authenticator
using ordinary equality — `==`, `===`, `strcmp`, `bytes.Equal` — where an attacker
can observe the timing and a constant-time API exists. Comparing two public values
(a content hash, an ETag) with `==` is not a finding.
- Roll your own crypto: custom XOR, custom HMAC, custom Diffie–Hellman, custom
signature schemes. Use audited primitives.
### KNOWN FALSE POSITIVES
- MD5 / SHA-1 in non-security contexts: HTTP ETag computation, content deduplication,
cache keying for non-sensitive data, fixture fingerprinting. Annotate these with a
`// non-security use: …` comment.
- Test vectors and KAT (Known Answer Test) values intentionally hardcode IVs, keys,
and plaintexts — they belong in `tests/`, not production.
- Legacy interoperability may genuinely require a deprecated primitive. Confine it to
the specific protocol boundary, prevent downgrade outside that boundary, document
the dependency and a removal plan, and never use the legacy primitive for newly
designed storage or protocols. A feature flag is an operational mechanism, not the
security control. Where a legacy CBC-plus-MAC construction survives, it must be
Encrypt-then-MAC — MAC-then-Encrypt is what made Lucky13 possible.
## Context (for humans)
The recurring failure modes are: fast hash for passwords (CWE-916), predictable RNG
for tokens (CWE-338), broken cipher choice (CWE-327), and non-constant-time
comparison of secrets (CWE-208). OWASP's storage and password-storage cheat sheets
are the practical companions to NIST's deprecation roadmap.
AI assistants tend to mirror whatever crypto example was popular on Stack Overflow
circa 2014, which means lots of `sha256(password)` and `AES-CBC` with manual padding.
This skill is the counterweight — but note the second failure mode it guards against:
rules that state a remembered constant as if it were permanent. Work factors, key-size
floors, and approved-algorithm lists all move. The rules above name where to look them
up rather than what they were on the day the rule was written.
## References
- `references/verifying-findings.md` — confirm or refute a finding, then lock it
- `rules/algorithm_blocklist.json`
- `rules/key_size_minimums.json`
- [OWASP Password Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html) — the source of record for KDF work factors.
- [OWASP Cryptographic Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html).
- [NIST SP 800-131A](https://csrc.nist.gov/publications/detail/sp/800-131a/rev-2/final) and [SP 800-57 Part 1](https://csrc.nist.gov/publications/detail/sp/800-57-part-1/rev-5/final) — check the CSRC page for a newer revision before citing a minimum.
- [CWE-327](https://cwe.mitre.org/data/definitions/327.html) — Broken or risky crypto.
- [CWE-916](https://cwe.mitre.org/data/definitions/916.html) — Insufficient computational effort for password hash.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!