Choosing the right primitive
Most cryptographic failures are not broken maths — they are the right algorithm used for the wrong job. This lesson is a lookup table you can keep.
In this lesson
- Map a requirement to a modern algorithm
- Explain why defaults beat clever designs
- Audit a codebase for legacy primitives
The decision table
| Requirement | Use | Avoid |
|---|---|---|
| Password storage | Argon2id, bcrypt, scrypt | SHA-256, MD5, encryption |
| File/message integrity | SHA-256, SHA-3, BLAKE3 | MD5, SHA-1 |
| Message authentication | HMAC-SHA-256 | Home-grown MACs |
| Data at rest / in transit | AES-256-GCM, ChaCha20-Poly1305 | ECB mode, DES, RC4 |
| Key exchange | X25519 (TLS 1.3) | Static RSA key exchange |
| Signatures | Ed25519, ECDSA P-256 | DSA, RSA PKCS#1 v1.5 padding |
| Random tokens / nonces | CSPRNG (random_bytes) | mt_rand, time(), UUIDv4 |
Example · A checklist for code review
Search the codebase for md5(, sha1(, AES/ECB, rand( and hard-coded IVs. Each hit is either a bug or a deliberate, documented exception.
Prefer libraries over algorithms
Use libsodium (NaCl), cryptography in Python, or your platform's TLS. You choose the primitive; the library handles nonces, padding and key derivation safely.
Break a weak design
Brute-force the Caesar cipher, then consider what "the algorithm is secret" bought the designer.
Match properties to primitives
Practice · server-gradedShould I ever invent my own protocol?
Composing proven primitives is hard enough — novel protocol design needs formal review and years of scrutiny. Use what TLS/Signal already solved.
What about post-quantum?
Hybrid key exchange (X25519 + ML-KEM) is already shipping in TLS. Plan migrations for long-lived secrets now.