iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

A02 Cryptographic Failures

A02:2021 — Cryptographic Failures — covers data not protected in transit, weak crypto, hard-coded keys, predictable randomness, broken authentication. The fix is “use the standard libraries the right way.”

TLS, hashing, key management, randomness

EXAMPLE
// 1) HTTPS / TLS — non-negotiable
# nginx — modern config
ssl_protocols              TLSv1.2 TLSv1.3;
ssl_ciphers                'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers  on;
ssl_session_cache          shared:SSL:50m;
ssl_session_timeout        4h;
add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload' always;

// 2) Hashing passwords — use a slow KDF (argon2id, scrypt, bcrypt)
// Node
import argon2 from 'argon2';
const hash = await argon2.hash(password, {
    type: argon2.argon2id, memoryCost: 19*1024, timeCost: 2, parallelism: 1,
});
await argon2.verify(stored, attempt);

// NEVER:
//   sha256(password)         — fast hash, GPU-bruteforce in seconds
//   md5(password)             — broken on every axis
//   sha256(password + salt)   — still too fast

// 3) Hashing data integrity — SHA-256 / SHA-3 / BLAKE3
import crypto from 'node:crypto';
const digest = crypto.createHash('sha256').update(data).digest('hex');

// 4) Authenticated encryption — AES-GCM or ChaCha20-Poly1305
const key = crypto.randomBytes(32);
const iv  = crypto.randomBytes(12);
const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
const ct = Buffer.concat([cipher.update(plaintext), cipher.final()]);
const tag = cipher.getAuthTag();
// Pack iv || ct || tag

// NEVER:
//   aes-256-cbc + your-own-HMAC — easy to mess up
//   aes-256-ecb                  — leaks structure (the famous penguin)

// 5) Random — only from a CSPRNG
const token = crypto.randomBytes(32).toString('base64url');   // OK
const uuid  = crypto.randomUUID();                            // OK
// NEVER: Math.random() for tokens / IDs / nonces / keys

// 6) Signing — HMAC for symmetric, RSA / ECDSA / Ed25519 for asymmetric
const sig = crypto.createHmac('sha256', key).update(message).digest('hex');
// Verify with constant-time compare:
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));

// JWTs — RS256 / ES256 / EdDSA. NEVER use 'none' or HS256 with a guessable secret.

// 7) Key management — the actual hard part
#   • Generate keys with a CSPRNG
#   • Store in a KMS / Secrets Manager (AWS KMS, GCP KMS, Vault, Doppler)
#   • NEVER commit keys to git
#   • Rotate periodically; envelope encryption (KEK / DEK)
#   • Use service identities (IAM roles) — never long-lived API keys in env files

// 8) PII at rest — encrypt sensitive fields
# Database-level: TDE (transparent disk encryption)
# Field-level:    encrypt(name, ssn, dob) with a per-tenant key
# Hash for search: HMAC(value, server_secret) — collisions stay deterministic

// 9) Avoid common mistakes
//   Hard-coded API keys in source
//   .env files committed to git
//   Secrets in logs / error messages / Sentry breadcrumbs
//   Cookies without Secure on HTTPS sites
//   Token comparison with `===` instead of timingSafeEqual
//   Building your own crypto primitives — use libsodium / @noble/* / vetted libraries

// 10) Compliance + standards
#   • OWASP ASVS level 2 covers crypto in detail
#   • NIST SP 800-63B for password storage
#   • PCI-DSS for cardholder data (encryption + tokenisation)
#   • GDPR / Australia Privacy Act — encryption is the de-facto control for PII

// 11) Audit checklist
#   - HTTPS-only with HSTS preload
#   - Modern TLS suites only (TLS 1.2/1.3)
#   - Passwords: argon2id / scrypt / bcrypt
#   - PII / payment data encrypted at rest with KMS-managed keys
#   - Tokens / sessions use crypto.randomBytes (not Math.random)
#   - No hard-coded secrets in source (gitleaks / trufflehog scan in CI)
#   - JWT signing keys are >= 256-bit, rotated, and stored in KMS
#   - Every secret has an owner + rotation schedule

// 12) Tools
#   • SSL Labs (https://www.ssllabs.com/ssltest/) — grade your HTTPS
#   • Mozilla Observatory — overall security headers
#   • testssl.sh — local TLS scanner
#   • gitleaks / trufflehog — scan repos for committed secrets
#   • OWASP ASVS checklist — formal coverage

Why it matters

Most crypto failures are mundane: weak hash on passwords, plaintext PII in the DB, secrets in git, Math.random() for tokens. Use vetted libraries with safe defaults; the “clever” crypto code is almost always the wrong move.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// A02 Cryptographic Failures — sensitive data at rest / in transit.
// Examples: HTTP for login, MD5 passwords, weak random tokens, hard-coded keys.
// Fix: TLS everywhere, argon2id for passwords, libsodium for crypto, KMS for keys.
Try it Yourself »

Discussion

Loading…