Chapter 9 — The real hash functions, and which are broken
In one sentence
MD5 and SHA-1 are broken and must not be used for security; SHA-2, SHA-3, and BLAKE2/3 are fine.
The table to memorise
| Algorithm | Output | Status | Use it? |
|---|---|---|---|
| MD5 | 128 bit | BROKEN — collisions found in seconds | Never for security. Non-security checksums only. |
| SHA-1 | 160 bit | BROKEN — practical collisions (SHAttered, 2017; chosen-prefix, 2020) | Never for new work |
| SHA-256 / SHA-512 (SHA-2) | 256 / 512 bit | Secure | Yes — the default |
| SHA-3 / SHAKE | variable | Secure, different internal design | Yes; useful as a hedge against SHA-2 |
| BLAKE2 / BLAKE3 | variable | Secure, very fast | Yes, where supported |
What "broken" actually means
The distinction matters, because "MD5 is broken" is often over- and under-stated.
COLLISION ATTACK -- find ANY two inputs with the same hash.
MD5: seconds on a laptop
SHA-1: ~2^63 work; done for real in 2017 (SHAttered)
-> breaks SIGNATURES and CERTIFICATES
CHOSEN-PREFIX COLLISION -- find a collision where you control both prefixes.
MD5: trivial
SHA-1: demonstrated in 2020, ~$45k of compute at the time
-> breaks practically everything; this is what killed SHA-1 for good
PREIMAGE ATTACK -- given a hash, find AN input producing it.
MD5: still not practical
SHA-1: still not practical
-> so "MD5 of a strong random value" isn't instantly broken...
but there is no reason to use it, and plenty of ways it bites you
Bottom line: MD5 and SHA-1 fail exactly where hashes matter most — proving that a document, certificate, or binary is the one you think it is.
The real-world consequences
Flame malware (2012) forged a Microsoft code-signing certificate using an MD5 chosen-prefix collision. It let malware appear to be a legitimate Windows Update. That is the practical meaning of "collisions break signatures".
SHAttered (2017) — Google and CWI produced two different PDF files with the same SHA-1 hash. Immediately afterwards, SHA-1 was removed from certificate issuance, and git had to add collision detection.
Choosing in practice
General-purpose hashing, integrity, signatures -> SHA-256
Need extra margin / long-term -> SHA-512 or SHA-3-256
Performance-critical (lots of data) -> BLAKE3
Hashing PASSWORDS -> NONE OF THESE (Chapter 10)
Legacy system compatibility only -> document the risk, plan removal
Simplified: SHA-512 is often faster than SHA-256 on 64-bit CPUs, despite the bigger output. If you want margin and speed, SHA-512 (or its truncated variant SHA-512/256) is a good pick.
Length-extension: a subtlety that matters
SHA-1 and SHA-2 have a structural quirk: given hash(secret || message) and the
length of secret, an attacker can compute hash(secret || message || extra)
without knowing the secret.
NAIVE (broken): token = sha256(secret + data)
-> attacker appends "&admin=true" and forges a valid token
CORRECT: token = HMAC-SHA256(secret, data) (Chapter 11)
SHA-3 and BLAKE2/3 are immune by design. But the right answer is always HMAC, not picking a different hash.
Practice (25 min)
cd ~/sec-lab/scratch
# --- compare algorithms and their output sizes ---
for alg in md5 sha1 sha256 sha512 sha3-256; do
printf "%-10s " "$alg"; printf 'hello' | openssl dgst -$alg 2>/dev/null | awk '{print $2}'
done
# --- speed comparison ---
openssl speed -evp sha256 2>/dev/null | tail -3
openssl speed -evp sha512 2>/dev/null | tail -3
# --- see a REAL MD5 collision ---
# Two different files, identical MD5. (Marc Stevens' classic example.)
curl -sO https://raw.githubusercontent.com/corkami/collisions/master/examples/free/md5_1.bin
curl -sO https://raw.githubusercontent.com/corkami/collisions/master/examples/free/md5_2.bin
cmp md5_1.bin md5_2.bin && echo "identical files" || echo "DIFFERENT files"
openssl dgst -md5 md5_1.bin md5_2.bin
openssl dgst -sha256 md5_1.bin md5_2.bin # SHA-256 tells them apart
That last exercise is worth doing properly. Two files that differ, with the same MD5. Once you've seen it, "MD5 is broken" stops being abstract.
Break it: write a script that verifies a download using MD5. Then explain, in
notes.md, exactly how an attacker who can also produce the "official" file
defeats your check.
Common confusions
- "MD5 is fine for checksums." For detecting accidental corruption, yes. For detecting deliberate tampering, no — and most checksum use is really about tampering.
- "I'll use MD5 then SHA-256, two hashes are safer." Concatenating hashes is barely stronger than the stronger one alone. Just use SHA-256.
- "SHA-256 is slow." It processes hundreds of MB/s per core, and most CPUs have hardware acceleration. It is not your bottleneck.
- "More output bits = more secure." Only to a point. 256 bits is beyond any foreseeable brute force; going bigger buys margin, not necessity.
Check yourself
- What does it mean that MD5 is "broken"? Which property fails?
- Why does a collision attack break digital signatures?
- What is a length-extension attack, and what's the correct fix?
- Which hash should you use by default in 2026?
Further reading
- Site:
shattered.io— Google's SHA-1 collision announcement, with the two colliding PDFs. Excellent and accessible. - Repository:
github.com/corkami/collisions— a collection of real hash collisions in many file formats. Superb for building intuition. - Guidance: NIST SP 800-131A — the official "which algorithms are still approved" document. Useful to cite in an argument.