Part II · 2 — Hash, MAC, and KDF
Encryption protects the secret; hash, MAC, and KDF protect integrity, authorship, and the keys themselves. They are the most reused primitives — and the most misused (passwords in SHA-256 "because it's secure" is a classic mistake).
2.1 Cryptographic hash functions
A hash compresses an input of any size into a fixed-size digest (e.g., 256 bits). To be cryptographic, it needs three properties:
| Property | Meaning | If broken… |
|---|---|---|
| Preimage resistance | Given a digest, it is infeasible to find an input that generates it. | Breaks passwords, commitments. |
| 2nd-preimage resistance | Given an input, it is infeasible to find another with the same digest. | Forges documents. |
| Collision resistance | It is infeasible to find any two inputs with the same digest. | Breaks signatures (it was the end of MD5 and SHA-1). |
Avalanche effect: flipping one input bit changes ~half the digest bits.
2.2 Which hashes to use (2026)
| Hash | Verdict |
|---|---|
| MD5, SHA-1 | ❌ broken (practical collisions). Only for non-adversarial checksums. |
| SHA-256 / SHA-512 (SHA-2) | ✅ solid standard, ubiquitous. |
| SHA-3 / Keccak | ✅ different design from SHA-2 (sponge) — a good hedge. |
| BLAKE3 | ✅ very fast, parallelizable; great for file integrity. |
A hash is not for storing passwords. It is fast on purpose — which helps the attacker test billions per second. Passwords require a slow KDF (section 2.5).
2.3 MAC: integrity with authorship
A hash guarantees that the data did not change — but anyone can recompute the hash of altered data. A MAC (Message Authentication Code) adds a secret key: only someone who has it produces a valid tag. It proves integrity and origin (among those who share the key).
- HMAC — builds a MAC from a hash (HMAC-SHA-256). Mature, standard.
- Poly1305 — fast MAC, used in AEAD with ChaCha20.
Remember the distinction from Part I: a MAC uses a shared key (it gives no non-repudiation); a signature uses a private key (it does). And always compare tags in constant time — comparing byte by byte with early exit becomes a timing side channel.
2.4 KDF: deriving keys from other keys
A KDF (Key Derivation Function) produces keys from other material. Two distinct uses:
- Key-material derivation — from a high-entropy secret
(e.g., the result of a Diffie-Hellman), generate several subkeys. Use HKDF (HMAC-based KDF): extract (concentrates the entropy) + expand (generates bytes).
- Stretching low entropy — predictable material needs a deliberately
expensive KDF — that is the case for passwords, below.
2.5 Password hashing: the special case
Passwords have low, human entropy. Storing them requires a function that is slow and memory-hard, plus a salt unique per password:
| Function | Note |
|---|---|
| Argon2id | ✅ current recommendation (resistant to GPU/ASIC via memory cost). |
| scrypt | ✅ good alternative with memory cost. |
| bcrypt | ✅ acceptable (solid legacy), without memory cost. |
| PBKDF2 | ⚠️ only when required by a standard; configure high iterations. |
| Raw SHA-256 | ❌ too fast — breakable en masse. |
- Salt — a public random value, unique per password, so that equal
passwords generate different hashes and break rainbow tables. Stored alongside.
- Pepper — a system-wide fixed secret, applied to all passwords and not
stored in the database; it vanishes with the secret if the database leaks on its own.
Rule: password → Argon2id (with a per-user salt). Key material from a handshake → HKDF. Never swap one for the other.
Dense reference: the complete catalog of hashes (BLAKE2, SHA-3, RIPEMD, Streebog, SM3), HMAC, and KDFs is in
06-hash-and-mac. Next: the leap to asymmetric cryptography — where the two sides stop needing a prior shared secret.