Crypto best practices
Skill pedromneto97/custom-skills/skills/crypto-best-practices
List of custom agent skills
npx -y skills add pedromneto97/custom-skills --skill crypto-best-practicesAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Cryptographic best practices for secure system design. Use when: choosing encryption algorithms, implementing password hashing, selecting key lengths, using secure random number generation, implementing digital signatures, designing TLS deployments, key management, or avoiding common cryptographic pitfalls.
SKILL.md
13.5 KB, as published. Nobody here has run it
Cryptographic Best Practices
⚠️ Golden Rule
Use a battle-tested library that handles cryptographic composition correctly for you:
- NaCl (by Daniel Bernstein)
- libsodium (NaCl fork by Frank Denis)
- monocypher (libsodium fork by Loup Vaillant)
If you use these libraries, most low-level decisions are already made for you. Only continue reading if forced to make your own choices.
1. Symmetric Encryption
Decision Tree:
- Do you have access to a Key Management System (KMS)? → Use KMS
- Otherwise → Use AEAD (Authenticated Encryption with Associated Data)
Recommended algorithms (in order):
- NaCl/libsodium/monocypher default
- ChaCha20-Poly1305 (faster in software)
- AES-GCM (industry standard, faster with AES-NI)
- AES-CTR with HMAC (fast in software)
❌ Avoid:
- AES-CBC, AES-CTR alone (must use AEAD)
- Block ciphers with 64-bit blocks (Blowfish, 3DES)
- OFB mode
- RC4 (broken)
Why AEAD? Prevents forged ciphertexts. A single byte corruption either fails authentication or reveals nothing.
2. Symmetric Key Length
Recommendations for data protection through 2050:
- Minimum: 128 bits
- Maximum: 256 bits (no harm in using larger)
| Standard | Recommendation | Notes |
|---|---|---|
| NIST | 192 bits | Conservative government standard |
| ECRYPT II | 256 bits | Academic consensus, most conservative |
| ANSSI | 128 bits | European standard, adequate |
| IAD-NSA | 256 bits | Highest security requirement |
If your symmetric key is derived from user input (password):
- The password must provide at least as many bits of entropy as the target key length
- Example: 128-bit AES key needs ≥128 bits of entropy in the password
3. Symmetric Signatures (HMAC/MAC)
Use when authenticating but not encrypting (e.g., API requests, message authentication).
Recommended algorithms (in order):
HMAC variants:
- HMAC-SHA-512/256 (truncated SHA-512)
- HMAC-SHA-512/224 (truncated SHA-512)
- HMAC-SHA-384
- HMAC-SHA-224
- HMAC-SHA-512
- HMAC-SHA-256
Alternatives (preferred by cryptographers):
- Keyed BLAKE2b
- Keyed BLAKE2s
- Keyed SHA3-512
- Keyed SHA3-256
❌ Avoid:
- HMAC-MD5
- HMAC-SHA1
- Custom "keyed hash" constructions
- Complex polynomial MACs
- Encrypted hashes
- CRC
Implementation tip: Always use a secure compare function to prevent timing attacks on MAC verification.
4. Hashing Algorithms
Use when you need collision-resistant, one-way hashing (not password hashing — see Section 5).
Recommended (pick one):
- SHA-2 (SHA-256, SHA-384, SHA-512): Fast, time-tested, industry standard
- BLAKE2 (BLAKE2b, BLAKE2s): Faster than SHA-3, SHA-3 finalist
- SHA-3 (SHA3-256, SHA3-512): Slowest but industry standard
❌ Avoid:
- SHA-1 (collision vulnerabilities proven)
- MD5 (broken)
- MD6
- EDON-R
Truncation note: SHA-2 output truncation (e.g., SHA-512/256) sidesteps length extension attacks and is safe.
5. Random Number Generation
Rule: Always use your operating system's CSPRNG (Cryptographically Secure Pseudo-Random Number Generator).
| OS | CSPRNG | Usage |
|---|---|---|
| Linux / BSD / macOS | /dev/urandom | Primary choice |
| Windows | CryptGenRandom | Primary choice |
Important: /dev/random is NOT more secure than /dev/urandom. They use the same CSPRNG; they differ only in blocking behavior.
Generate: 256-bit random numbers as default.
Fallback (constrained environments only):
- Use fast-key-erasure if you're in embedded firmware where OS RNG unavailable
- Requires careful entropy seeding on each boot (difficult to get right)
- Last resort only
❌ Avoid:
- Userspace RNG
- Predictable seeds (
srand(time())) - Weak PRNGs for cryptographic use
6. Password Hashing
Use when storing user passwords in a database.
Algorithm Selection
Recommended (in order):
-
Argon2id (winner of Password Hashing Competition)
- Tune appropriately: sufficient CPU time + RAM allocation
- Shows no serious weaknesses, well-analyzed
-
scrypt (≥16 MB RAM)
- Sensitive to parameters; can be weaker than bcrypt if misconfigured
- Time-memory tradeoff attacks possible
-
bcrypt (≥cost 5)
- Use as:
bcrypt(base64(SHA-512(password))) - Mitigates 72-character password limit + leading NULL byte problem
- Use as:
-
SHA-512-crypt (≥5,000 rounds)
- Older but acceptable
-
SHA-256-crypt (≥5,000 rounds)
-
PBKDF2 (≥600,000 rounds per OWASP 2023)
- Industry standard, but higher iteration count needed
❌ Avoid:
- Plaintext passwords
- Naked SHA-2, SHA-1, MD5
- Custom homebrew algorithms
- Any encryption algorithm (for password storage)
Cost Parameters
| Algorithm | Parameter | Minimum | Recommendation |
|---|---|---|---|
| Argon2id | Time cost + Memory cost | - | Tune to CPU/RAM available (≥3s on target hardware) |
| scrypt | N, r, p | N≥16384 | ≥16 MB RAM allocation |
| bcrypt | Cost factor | 5 | 10-12 (tune for ≤100ms latency) |
| SHA-512-crypt | Rounds | 5,000 | 5,000-10,000 |
| SHA-256-crypt | Rounds | 5,000 | 5,000-10,000 |
| PBKDF2 | Iterations | 600,000 | 600,000+ (increase with time) |
7. Asymmetric Encryption
Stop using RSA. Use ECC (Elliptic Curve Cryptography).
Reasons to prefer ECC:
- Attacks on RSA proceeding faster than on ECC
- RSA encourages insecure direct encryption (loses forward-secrecy)
- ECC puts security burden on cryptographers (good), not implementors (bad)
- Fewer knobs to turn = fewer mistakes
If you absolutely must use RSA:
- Use RSA-KEM (not raw RSA encryption)
- But really, use ECC instead
Recommended approach:
- Use NaCl/libsodium/monocypher, which provide safe ECC-based encryption by default
❌ Avoid:
- Raw RSA encryption/decryption
- ElGamal
- OpenPGP, OpenSSL, BouncyCastle for new projects (too many knobs)
8. Asymmetric Key Length
For data protection through 2050:
| Scheme | Minimum | Recommended | Protection |
|---|---|---|---|
| ECC/ECDH | 256 bits | 256 bits | ~128-bit symmetric equivalent security |
| RSA/DH Group | 2048 bits | 3072+ bits (if forced) | Equivalent to ~112-bit symmetric |
Ratios: ECC 256-bit ≈ RSA 2048-bit in security strength.
Personal recommendation:
- 256-bit minimum for ECC/ECDH keys
- 2048-bit minimum for RSA/DH (but you shouldn't use RSA)
9. Asymmetric Signatures
Deterministic signatures are misuse-resistant.
Recommended (in order):
- NaCl/libsodium/monocypher (handles everything)
- Ed25519 (NaCl default, most popular non-Bitcoin signature scheme)
- RFC 6979 (deterministic DSA/ECDSA)
Why deterministic? Protects against failures like the PlayStation 3 ECDSA flaw, where nonce reuse leaked private keys.
❌ Avoid:
- ECDSA (unless using deterministic RFC 6979)
- DSA
- RSA signatures
10. Diffie-Hellman Key Exchange
Golden rule: Don't roll your own encrypted transport. Use NaCl.
If you must implement key exchange:
Recommended (in order):
- NaCl/libsodium/monocypher (use this!)
- Curve25519 (carefully chosen to minimize implementation errors)
- 2048-bit DH Group #14 (if Curve25519 unavailable)
Curve25519 is special: The entire curve was designed to prevent common implementation mistakes.
Important: Use an Authenticated Key Exchange (AKE) that resists Key Compromise Impersonation (KCI).
❌ Avoid:
- NIST curves with ECDH (point validation bugs leak secrets)
- Conventional DH negotiation
- SRP, J-PAKE
- Elaborate key negotiation schemes
11. Website Security (HTTPS/TLS)
Recommendation: Use a web hosting provider that manages TLS for you (AWS, Heroku, etc.).
If you self-host:
-
Use OpenSSL (not LibreSSL, BoringSSL, BearSSL)
- OpenSSL is on-the-ball with vulnerability disclosure
- Others don't justify the added complexity for new projects
-
Use Let's Encrypt for certificates
- Free, automated, and solid
- Set up cron for regular re-fetches
Configuration: Hardcode these settings
- TLS 1.2 or higher (no downgrade negotiation)
- ECDHE cipher suites only (forward secrecy)
- AES-GCM cipher only
Modern TLS policy example:
ECDHE-ECDSA-AES256-GCM-SHA384:
ECDHE-RSA-AES256-GCM-SHA384:
ECDHE-ECDSA-AES128-GCM-SHA256:
ECDHE-RSA-AES128-GCM-SHA256
❌ Avoid:
- Default TLS configuration
- Negotiable cipher suites (prevents downgrade attacks)
- Export-grade ciphers (FREAK, Logjam attacks)
- CBC mode ciphers (BEAST, Lucky13, CRIME)
12. Client-Server Application Security
Scenario: Custom transport layer (not browser-based).
Use TLS because:
- Many TLS vulnerabilities require browser JavaScript execution
- You control both client and server (no CA risk)
- You can self-sign and ship cert with code
- Standard approach proven at scale
Why not roll your own? See Salt Stack's e=1 RSA disaster (RSA with exponent = 1 = encrypted plaintext).
If implementing custom transport over TLS:
- Hardcode TLS 1.2+
- ECDHE ciphers only
- AES-GCM only
- No negotiation
13. Online Backups
Best practice: Host backups yourself.
Recommended approaches (in order):
- OpenZFS with redundancy + 256-bit checksums (best)
- Tarsnap (cloud-based, encrypted client-side, proven)
- Keybase KBFS (end-to-end encrypted, 250GB free, but closed ecosystem)
Cloud storage (❌ Avoid):
- Google, Apple, Microsoft: Trust-based
- Dropbox: Trust-based
- Amazon S3: No end-to-end encryption by default
14. Hybrid Encryption (Combining Asymmetric + Symmetric)
When: Encrypting long messages with public key cryptography.
Process:
- Generate random symmetric key (e.g., 256-bit)
- Encrypt message with symmetric cipher (AES-GCM)
- Encrypt symmetric key with asymmetric encryption (Curve25519 / ECC)
- Send: encrypted key + encrypted message
NaCl/libsodium/monocypher handle this automatically in high-level APIs (crypto_box_easy).
15. Common Implementation Pitfalls
| Pitfall | Impact | Fix |
|---|---|---|
| Nonce reuse in AEAD | Leaks auth key, breaks encryption | Generate fresh nonce each time, use AEAD-SIV for nonce-reuse resistance |
| Timing attacks on MAC | Attacker forges messages | Use constant-time comparison |
| Crypto canonicalization bugs | HMAC input variations leak secrets | Document exact input format, use NaCl |
| Key derivation from weak passwords | Weak keys from "secure" storage | Use password hashing (Argon2), sufficient CPU cost |
| Hot-loading unvalidated keys | Attacks on ECC points | Use libraries that validate key format |
| Mixing encryption contexts | Nonce confusion, key reuse | Unique key + IV per context, use NaCl |
16. Quick Reference Matrix
| Task | Algorithm | Min Key Size | Library |
|---|---|---|---|
| Encrypt data at rest | ChaCha20-Poly1305 or AES-GCM | 256 bits | libsodium |
| Sign API requests | HMAC-SHA-512/256 | 256 bits | libsodium |
| Hash data | SHA-2 or BLAKE2b | N/A | libsodium |
| Generate random ID | OS CSPRNG (/dev/urandom) | 256 bits | OS |
| Hash password | Argon2id | Tune time+memory | libsodium |
| Public key encryption | Curve25519 (ECC) | 256 bits | libsodium |
| Digital signature | Ed25519 | 256 bits | libsodium |
| Key exchange | Curve25519 | 256 bits | libsodium |
| Website HTTPS | AES-GCM + ECDHE | 256 bits | OpenSSL + Let's Encrypt |
17. Decision Flowchart
START: I need cryptography
├─ "I should just use NaCl/libsodium/monocypher"
│ └─ STOP ✓ (90% of cases)
│
├─ "I must implement a choice myself"
│ │
│ ├─ Symmetric encryption?
│ │ └─ ChaCha20-Poly1305 or AES-GCM (with AEAD)
│ │
│ ├─ Password storage?
│ │ └─ Argon2id (tune time+memory)
│ │
│ ├─ Message authentication only?
│ │ └─ HMAC-SHA-512/256 or Keyed BLAKE2b
│ │
│ ├─ General hashing?
│ │ └─ SHA-2 or BLAKE2
│ │
│ ├─ Random numbers?
│ │ └─ /dev/urandom (or OS equivalent)
│ │
│ ├─ Public key encryption?
│ │ └─ NaCl curve25519_xsalsa20poly1305
│ │
│ ├─ Digital signatures?
│ │ └─ Ed25519 or NaCl default
│ │
│ ├─ Key exchange?
│ │ └─ Curve25519 (not DH-1024)
│ │
│ └─ Website HTTPS?
│ └─ OpenSSL + Let's Encrypt (ECDHE + AES-GCM)
Further Reading
- NaCl.cr.yp.to — Original library documentation
- Latacora Cryptographic Right Answers — Similar guidance
- SafeCurves — Guidance on elliptic curve safety
- OWASP Password Storage — Password hashing standards
- Noise Protocol Framework — Authenticated encryption protocol
- PASETO — Secure alternative to JWT