41 min read

How the Hash Functions Broke in Real Life: MD5, Flame, SHATTERED, and the Long Death of SHA-1

MD5 and SHA-1 were genuinely, mathematically broken -- yet every real breach still needed a second failure: a deployment still trusting the dead hash.

Permalink

1. The Forged Certificate That Rode Windows Update

In the spring of 2012, espionage malware called Flame spread through the Middle East wearing a disguise almost nothing could see through: it arrived signed by Microsoft, and reached some targets through Windows Update itself [1]. To a defending machine, it looked like a legitimate patch from the one vendor it trusted most. To forge that signature, its operators did something the open cryptographic literature had not yet published. They engineered a chosen-prefix collision in MD5 -- a hash academics had called broken since 2004 [2] -- and counterfeited a certificate that chained up to Microsoft's own root of trust [3].

The certificate they forged was not a plainly-issued code-signing certificate. It was a Terminal Server Licensing Service certificate living inside Microsoft's Enforced Licensing public-key infrastructure -- an obscure corner of Microsoft's PKI that the company was, in 2012, still signing with MD5. When Microsoft published Security Advisory 2718704 on 3 June 2012, the fix was to revoke exactly those certificates: the "Microsoft Enforced Licensing Intermediate PCA" and the "Microsoft Enforced Licensing Registration Authority CA" [4].

Cryptographic hash function

A deterministic function that compresses a message of any length into a short, fixed-length string called a digest (or hash). The same input always yields the same digest, a different input almost always yields a different one, and the function is designed to be one-way: easy to compute forwards, infeasible to invert.

The unsettling part of Flame is not that the math failed. It is that the math had failed nearly a decade earlier, in a Chinese cryptographer's paper read at a 2004 conference, and Microsoft's licensing servers were still signing with it eight years later. A broken primitive sat, patiently, underneath a live production certificate authority until someone with a nation-state budget decided to point a collision at it.

Now hold one more artifact in your head, because you will learn to read it by the end of this article. It is a SHA-1 digest:

38762cf7f55934b34d179ae6a4c80cadccbb7f0a

In February 2017, researchers at CWI Amsterdam and Google published two different PDF files that both hash to exactly that value [5]. Two distinct documents, one fingerprint -- a thing that was supposed to be computationally impossible for the hash guarding TLS certificates, Git commits, and software signatures across the internet.

That diagnostic sentence is the spine of everything that follows. It is also why this article is the honest exception in a series otherwise arguing that the deployment breaks, not the math. Here the math genuinely broke. And even here, on the one topic where the primitive itself fell, no attacker ever won on cryptanalysis alone. They won where broken math met a system still trusting it.

So if MD5 was known-broken years before Flame, why was anything still signing with it? To answer that, we have to be precise about what a hash actually promises -- because only one of its promises is fragile, and it is the exact one a certificate leans on.

2. What a Hash Promises, and Which Clause Is Fragile

A cryptographic hash function makes three separate promises. They sound similar, they are routinely confused, and telling them apart is the difference between understanding this whole story and mis-stating it. Only one of the three is fragile, and it is the one certificates depend on.

Preimage resistance

Given a target digest h, it is infeasible to find any message m such that hash(m) = h. This is the "one-way" promise: you cannot run the function backwards from an output to an input.

Second-preimage resistance

Given a specific message m1, it is infeasible to find a different message m2 with the same digest. The attacker is handed one input and must match its fingerprint with another.

Collision resistance

It is infeasible to find any two messages m1 and m2, both of the attacker's choosing, that produce the same digest. Nobody hands the attacker a target. They get to pick both sides. This is the weakest promise to keep, and the one every certificate and signature quietly relies on.

The gap between those last two properties is not cosmetic; it is exponential, and it has a name.

Birthday bound

For an n-bit digest, finding a collision takes only about 2^(n/2) work, not 2^n. The name comes from the birthday paradox: in a room of just 23 people, two probably share a birthday, because what matters is the number of pairs, which grows quadratically. Collisions among many hashes are similarly cheap.

That square-root haircut is brutal. By that bound, a 128-bit MD5 digest [6] offers only about 2642^{64} collision security, and a 160-bit SHA-1 digest only about 2802^{80}. Preimage and second-preimage attacks still cost close to the full 21282^{128} or 21602^{160}, which is why -- spoiler for Section 8 -- those properties survived while collision resistance did not. When you hear "MD5 is broken," the precise statement is "MD5's roughly 2642^{64} collision barrier fell far below 2642^{64}." It is not "you can invert an MD5 hash."

PropertyInformal promiseGeneric attack costWhat it protects
Preimage resistanceCannot find any message for a given digestabout 2^nPassword storage, commitments
Second-preimage resistanceCannot match a given message's digest with anotherabout 2^nIntegrity of one known file
Collision resistanceCannot find any two messages sharing a digestabout 2^(n/2)Certificates, signatures, content addressing

One construction under all of them

MD5, SHA-1, and SHA-2 are not three unrelated designs. They are three members of one family, built from the same skeleton.

Merkle-Damgard construction

A design that turns a fixed-size compression function into a hash for arbitrary-length messages. You start from a fixed initial value (the IV), split the padded message into blocks, and feed each block plus the running state through the compression function. The final state is the digest.

Ctrl + scroll to zoom
The Merkle-Damgard construction that MD5, SHA-1, and SHA-2 all share: a fixed compression function iterated over message blocks, starting from a fixed IV.

Ronald Rivest published MD5 in April 1992 as RFC 1321, producing a 128-bit digest [6]. Rivest is the "R" in RSA. MD5 was his hardened successor to MD4, and RFC 1321 says it "backs off" from MD4's speed for a "greater likelihood of ultimate security." The US government's SHA lineage followed a parallel path: SHA (retroactively SHA-0) arrived in FIPS 180 in 1993, and SHA-1 replaced it in FIPS 180-1 on 17 April 1995 with a 160-bit digest [7]. SHA-0 was withdrawn within about two years for an undisclosed weakness. SHA-1 differs from it by a single added one-bit rotation in the message schedule -- a fix whose importance Section 3 makes concrete.

Why a collision is a forgery

Here is the load-bearing fact that ties the fragile clause to the real world. A digital signature does not sign your whole message. It signs the hash of your message, because the message may be gigabytes and the signing math is slow. The signer computes a digest, then encrypts that short digest with a private key.

Ctrl + scroll to zoom
Signing operates on the digest, not the message. If two messages share a digest, one signature is valid for both.

Follow the consequence. If an attacker finds two messages with the same digest, and persuades someone to sign the harmless one, that same signature is automatically valid on the malicious one. The certificate authority signs a benign-looking certificate request; the attacker walks away with a valid signature on a forged certificate that shares its hash. Collision resistance is the only thing standing between "sign this document" and "you just signed a document you never saw."

Python Birthday bound: why 160 bits buys only 80-bit collision security
import math

# Collision work is about 2^(n/2), not 2^n, for an n-bit digest.
for name, n in [("MD5", 128), ("SHA-1", 160), ("SHA-256", 256)]:
  collision_exponent = n // 2
  print(name, "-", n, "bit digest ->", "collision work about 2^" + str(collision_exponent))

# Intuition: after hashing roughly 1.2 * sqrt(2^n) random messages,
# a collision is more likely than not.
n = 128
threshold = 1.2 * math.sqrt(2 ** n)
print("MD5: about {:.2e} messages before a coin-flip collision".format(threshold))

Press Run to execute.

RFC 1321 never proved MD5 collision-resistant. It only conjectured the property, in a sentence worth reading with hindsight.

"It is conjectured that it is computationally infeasible to produce two messages having the same message digest." -- RFC 1321, 1992 [6]

A conjecture, never a theorem. Cryptographers knew the difference, and some of them had already started chipping at the conjecture the year before Rivest even published. So they warned everyone. Did anyone listen?

3. The Writing on the Wall

For more than a decade before anyone forged anything, cryptographers kept saying the same thing about MD5: stop using it. Almost nobody did. The story of that decade is a slow-motion argument between two groups who were both right on their own terms -- academics who could see the primitive weakening, and deployers who could not yet see a working attack, and so kept shipping.

The first crack appeared a year after MD5 shipped. In 1993, Bert den Boer and Antoon Bosselaers found a pseudo-collision in MD5's compression function: two different initial values that, with the right inputs, produced the same output [8]. This was not a break of MD5 as deployed, because real MD5 fixes the initial value to a constant. It was a warning that the internal machine was not the ideal object it was assumed to be.

Three years later the warning got louder. In 1996, Hans Dobbertin found an actual collision in MD5's compression function -- same fixed structure, colliding outputs [9]. Dobbertin's result circulated as a rump-session manuscript and a writeup in RSA's newsletter CryptoBytes 2(2), not as a refereed EUROCRYPT '96 proceedings paper, a detail frequently miscited. Its existence is corroborated by RFC 2104's reference list. Dobbertin himself told people to migrate. The response from the deploying world was, roughly, that a compression-function collision is not a full-message collision, and until someone shows two real files with the same MD5, there is nothing to fix. They were technically correct, and that correctness bought them eight more years of complacency.

The government's SHA line got its own warning shot in 1998, when Florent Chabaud and Antoine Joux demonstrated differential collisions in SHA-0 [10]. Their paper mattered beyond SHA-0 for two reasons. First, it introduced the differential-path method -- steering tiny input differences through the rounds so they cancel -- that would later break MD5 and SHA-1 for real. Second, it proved that the single one-bit rotation NIST had quietly added to turn SHA-0 into SHA-1 was load-bearing: exactly the fix that made SHA-1 resist the SHA-0 attack. The lineage was visibly fragile, and its designers knew which thread to pull.

2004: the conjecture falls

Then came the hinge year. At the CRYPTO 2004 rump session, Xiaoyun Wang and colleagues Dengguo Feng, Xuejia Lai, and Hongbo Yu presented the first practical full MD5 collision -- two complete messages with the same digest, found not in theory but in hours of computation [2]. The result was announced to a packed rump-session room and formalized the next year as "How to Break MD5 and Other Hash Functions" at EUROCRYPT 2005. The next year, Wang and Yu published the method in full [11], and Wang, with Yiqun Lisa Yin and Hongbo Yu, turned the same differential machinery on SHA-1: an attack at roughly 2692^{69} operations, comfortably below SHA-1's 2802^{80} birthday bound, and the first sign that SHA-1's clock was running too [12].

The escalation is the whole point. The warnings climbed a ladder of severity: the compression function is not ideal (1993), the compression function collides (1996), the design method is exploitable (1998), here are two real colliding files (2004), and the successor is falling too (2005). At each rung, deployers had a defensible reason to wait -- until the rung above made waiting indefensible.

And yet here is the puzzle that should bother you. Wang produced real, reproducible MD5 collisions in 2004. Certificate authorities kept issuing MD5-signed certificates until 2008 and beyond. Were they simply negligent for four years? Not entirely. Because in 2004, a collision still could not target a victim. Understanding why not is the single most important idea in this article.

4. The Collision-Capability Ladder

Here is the counterintuitive fact that explains the four-year gap between Wang's 2004 collision and the first real forgery in 2008: a hash collision is not automatically a forgery. Wang could produce two files with the same MD5 digest, but she could not choose what those two files said. That distinction is not a footnote. It is the entire difference between an academic curiosity and a weapon, and it sorts the whole history into a four-rung ladder, where each rung is strictly more dangerous than the one below.

Ctrl + scroll to zoom
The four-rung collision-capability ladder. Each rung is strictly more powerful than the one below; only rung three can forge a certificate.

Rung 1 we have already met: pseudo-collisions and compression-function collisions, where the attacker is allowed to vary the initial value [8, 9]. These are warnings, not weapons, because a deployed hash nails the IV to a published constant. The attacker never gets that freedom in the field.

Rung 2 is the identical-prefix collision, and it is what Wang achieved for MD5 in 2004.

Identical-prefix collision

Two messages that begin with the same chosen prefix, followed by carefully computed collision blocks, that produce the same digest. The two messages end up near-twins, differing only in a small block of engineered gibberish. The attacker controls the shared prefix but cannot make the two messages say two different meaningful things.

An identical-prefix collision is genuinely dangerous to some systems. It breaks naive content-addressing and adversarial deduplication, because two different byte streams now share an identifier. It is exactly what SHATTERED delivered against SHA-1 in 2017: two PDFs, same prefix, same 263.12^{63.1}-effort collision, same digest 38762cf7... [5]. But notice what it cannot do. It cannot collide a certificate that says "example.com, not a CA" with one that says "any website, is a CA," because those two documents do not share a prefix -- they differ in the fields that matter most. For that, you need the top rung.

Rung 3 is the chosen-prefix collision, and it is the hinge of this entire article.

Chosen-prefix collision

Two completely different, attacker-chosen prefixes -- say, two certificates naming two different identities -- that the attacker then extends with computed collision blocks until both sides reach the same digest. Unlike the identical-prefix case, the two documents can say whatever the attacker wants up front. This is the capability that converts a collision into a forgery.

Ctrl + scroll to zoom
Identical-prefix versus chosen-prefix collisions. Only the chosen-prefix attack lets two different identities converge to one digest.

Marc Stevens, Arjen Lenstra, and Benne de Weger built the first chosen-prefix collision for MD5 in 2007, and demonstrated it with two X.509 certificates for two different identities sharing one MD5 digest [13]. That result, more than Wang's, is the moment MD5 became forgeable in practice rather than in principle [14]. Rung 4 -- pointing that capability at a real, still-MD5 certificate authority -- is Section 5.

Chosen-prefix is the hinge. An identical-prefix collision makes look-alike twins that cannot lie about who they are. A chosen-prefix collision forges two different identities under one digest. Everything that separates "SHA-1 is theoretically dead" from "your certificate was just counterfeited" lives on that one rung.

Two ladders that rhyme

The remarkable thing is that SHA-1 climbed the exact same ladder as MD5, roughly a decade behind, rung for rung.

Ctrl + scroll to zoom
Two rhyming ladders. MD5 (1992 to 2012) and SHA-1 (1995 to 2020) fell in the same order: theory, then identical-prefix, then chosen-prefix, then weaponization.

SHA-1's descent ran from the 2005 theoretical attack, through a 2015 freestart collision that showed a real one was imminent [15], to SHATTERED's identical-prefix collision in 2017 [5], and finally to a chosen-prefix collision in 2020 [16]. Same four rungs, same order.

RungCapabilityLandmark examplesWork factorWhat it breaks
1Compression-function / pseudo-collision (free IV)den Boer-Bosselaers 1993, Dobbertin 1996internal onlynothing deployed (IV is fixed)
2Identical-prefix collision (near-twins)Wang 2004 (MD5), SHATTERED 2017 (SHA-1)~2^63.1 for SHA-1content addressing, dedup
3Chosen-prefix collision (two identities)Stevens et al. 2007 (MD5), Shambles 2020 (SHA-1)~2^63.4 for SHA-1certificates, signatures
4Weaponization against a live deploymentrogue CA 2008, Flame 2012, GnuPG 2020plus a trusting systemreal breaches

So by 2007, the world contained a laboratory capability to forge a certificate for anyone, under MD5. All it needed was a certificate authority still willing to sign with MD5. There was one. There were several.

5. Weaponization: Where Capability Met a Deprecated-but-Still-Live Deployment

A chosen-prefix collision is inert. On its own it is a lab artifact, a pair of files in a researcher's directory. It becomes a breach only when it is pointed at a system that is still signing with the broken hash. Watch that happen four times over twelve years, and each time, look for the second failure -- the one that is not about mathematics at all.

2008: the rogue certificate authority

In December 2008, a team including Alexander Sotirov, Marc Stevens, Jacob Appelbaum, Arjen Lenstra, David Molnar, Dag Arne Osvik, and Benne de Weger walked onstage at the 25th Chaos Communication Congress and announced that they had forged a certificate authority. Not stolen one -- forged one, with mathematics [17]. They obtained a legitimate end-entity certificate from the commercial CA RapidSSL, whose to-be-signed bytes had been engineered to collide, under MD5, with a second certificate carrying basicConstraints set to CA:TRUE -- a certificate that could itself issue certificates for any website on the internet [18].

The math failure was a chosen-prefix MD5 collision costing about 2492^{49} compressions, run on roughly 200 Sony PlayStation 3 consoles. To make the two certificates collide, they hid a 204-byte collision block inside a larger, roughly 427-byte span of parser-irrelevant data in the certificate's "Netscape Comment" extension, nicknaming that meaningless span a "tumor" [18]. But that was only half the demonstration. The other half: RapidSSL was still issuing MD5-signed certificates in 2008, four years after Wang, with predictable serial numbers and timestamps that let the team pre-compute the colliding prefix. Both failures, side by side, in one clean demo.

Ctrl + scroll to zoom
The rogue-CA and Flame weaponization pattern: a chosen-prefix collision transplants a real signature onto a forged certificate that a relying party then trusts.

2012: Flame, and an attacker ahead of academia

Return to the malware from the opening. When Marc Stevens examined the fraudulent certificate Flame carried, he found something that should not exist. Using a technique he called counter-cryptanalysis, he reconstructed the collision and proved the operators used a chosen-prefix MD5 variant not yet in the open cryptographic literature [3]; Max Fillinger and Stevens later fully reverse-engineered it [19]. The conclusion was as unsettling as Flame. A classified actor had been ahead of academia, and spent its secret capability on one target: a Microsoft licensing certificate the Enforced Licensing PKI still MD5-signed [4], then rode into Windows Update [1]. Marc Stevens defended his PhD thesis, "Attacks on Hash Functions and Applications," on 19 June 2012 -- sixteen days after Microsoft's Flame advisory, and just before he would reverse-engineer the very attack Flame used [20].

2017: SHATTERED

In February 2017, CWI Amsterdam and Google announced the first full SHA-1 collision: two PDFs sharing 38762cf7f55934b34d179ae6a4c80cadccbb7f0a [5]. The compute bill was enormous -- roughly nine quintillion SHA-1 computations, about 263.12^{63.1} operations, measured as approximately 6,500 CPU-years plus 110 GPU-years across Google's infrastructure. Both SHATTERED PDFs remain downloadable, and both still hash to 38762cf7.... You can verify the collision yourself with any SHA-1 tool [5]. But SHATTERED was an identical-prefix collision. It broke SHA-1 for content addressing and piled pressure on Git and Subversion, whose object identifiers are SHA-1 digests -- yet it could not, by itself, forge a certificate for a chosen identity. It proved SHA-1 dead as a collision-resistant hash without demonstrating impersonation. That final rung waited three more years.

2020: Shambles

In January 2020, Gaetan Leurent and Thomas Peyrin delivered the chosen-prefix SHA-1 collision and named it Shambles [16]. They drove the cost down to about 263.42^{63.4}, ran it on roughly 900 Nvidia GTX 1060 GPUs for under 100,000 US dollars, and used it to forge a PGP/GnuPG identity certification -- a Web-of-Trust signature transferable onto a forged key bearing someone else's name [22]. It carried CVE-2019-14855. The second failure was textbook: GnuPG 1.4 still defaulted to SHA-1 for identity certification. The fix, GnuPG 2.2.18, rejects SHA-1 identity signatures made after 19 January 2019.

"All attacks that are practical on MD5 are now also practical on SHA-1." -- Gaetan Leurent and Thomas Peyrin, SHA-1 is a Shambles, 2020 [16]

Four breaks, one shape

Lay the four incidents in a row and the pattern is impossible to miss. Every single one required both a fallen primitive and a live deployment that had not stopped trusting it.

Incident (year)Hash and rungThe math failureThe deployment failureSource
Rogue CA (2008)MD5, chosen-prefix~2^49 on ~200 PS3s, forged CA:TRUE intermediateRapidSSL still issuing MD5 certificates[18]
Flame (2012)MD5, chosen-prefix (novel)collision variant ahead of open literatureMicrosoft Enforced Licensing PKI still MD5-signing[3]
SHATTERED (2017)SHA-1, identical-prefix~2^63.1, first full SHA-1 collisionSHA-1 still addressing PDFs, Git, and SVN objects[5]
Shambles (2020)SHA-1, chosen-prefix~2^63.4, under 100k USDGnuPG 1.4 still defaulting to SHA-1[16]

Every breach needed two failures at once: a fallen primitive AND a deprecated-but-still-live deployment. RapidSSL in 2008, Microsoft's licensing PKI in 2012, GnuPG 1.4 in 2020 -- in each case the cryptanalysis was necessary, and in each case it was the still-trusting system that turned a lab result into a compromise. This is how the honest exception stays true to the series: the math genuinely fell, and it still was not enough on its own.

Four undisputed, reproducible breaks over twelve years is not an anecdote. It is a base rate. So what did the industry build to answer it?

6. The Fix, and the Base Rate It Earns

The four breaks were evidence for a bill the entire internet had to pay: migrate off the broken hashes, and build successors that would not fall the same way. Two answers emerged, and they are architecturally different on purpose.

The first is SHA-2, standardized in 2002 and consolidated in FIPS 180-4 [23]. SHA-2 keeps the Merkle-Damgard skeleton, but it does two things its predecessors did not. Its most common form, SHA-256, produces a 256-bit digest, lifting the collision ceiling from SHA-1's 2802^{80} to a comfortable 21282^{128}. And its message schedule is strongly non-linear, which denies the Wang-style differential trails that steered small differences through MD5 and SHA-1 to cancel. The same construction, but hardened against the exact technique that broke the family.

The second answer is SHA-3, standardized as FIPS 202 in 2015 [24]. SHA-3 is not a patched Merkle-Damgard hash at all. It is Keccak, a structurally different sponge construction, and NIST was explicit that it arrived as a supplement to SHA-2, not a replacement. That word choice matters, and Section 7 is about why keeping two unlike designs alive is a deliberate strategy rather than indecision.

Retiring a primitive is a deployment problem

Designing a successor is the easy half. The hard half is retiring a primitive that billions of systems already trust, and that history is a deployment history, written by standards bodies rather than cryptographers.

Year(s)MilestoneWhat it meant in practice
2011-2019NIST SP 800-131A, through Rev. 2MD5 and SHA-1 disallowed for generating new digital signatures [25]
2016-2017Public CAs and browsers sunset SHA-1 TLSNew publicly trusted SHA-1 certificates refused; browsers distrust existing ones [26]
2017sha1dc shipped into Git and GitHubDefensive collision detection buys migration time [27]
2022NIST announces SHA-1 retirementFull federal phase-out by 31 December 2030 [26]
2030FIPS 180-5 to remove the SHA-1 specFederal end of life for SHA-1 [26]

The engineering band-aid that bought a decade

Standards move slowly, and in 2017 the world still ran on SHA-1 in a thousand places that could not be changed overnight -- Git chief among them. So Marc Stevens and Dan Shumow built something clever: a hardened SHA-1 that detects when it is being attacked [27].

Their sha1dc library computes SHA-1 normally, but watches for the fingerprints of a collision attack in progress. It detects any cryptanalytic collision attack using any of the top 32 SHA-1 disturbance vectors with probability 1, at a false-positive probability below 2902^{-90}, for less than twice the cost of plain SHA-1. In its "safe-hash" mode it perturbs the output for a detected attack, so a colliding input no longer produces the colliding digest the attacker engineered. GitHub and Git integrated it directly, which is why pushing the SHATTERED PDFs to GitHub is rejected rather than silently accepted.

Step back and look at what this whole apparatus is. SHA-2, SHA-3, the SP 800-131A timeline, the 2030 retirement, and sha1dc are not five unrelated engineering decisions. They are the industry's collective response to a measured base rate: four weaponized breaks in twelve years, on two primitives, both of which climbed the same capability ladder to the same fatal rung. The migration to SHA-2 and SHA-3 is not caution in the abstract. It is a bill the evidence already justified.

But that raises a question the newer standard makes unavoidable. If SHA-3 is the more modern design, why did NIST tell everyone they did not need to switch to it?

7. Diversification, Not Supersession

Intuition says the newer standard should replace the older one. It says SHA-3, arriving in 2015, should retire SHA-2 the way SHA-2 retired SHA-1. NIST says the opposite: there is "no need to transition applications from SHA-2 to SHA-3" [28]. To see why that is not laziness, you have to notice that two different things have been happening at once, on two different axes.

One axis is supersession: MD5 gave way to SHA-1 gave way to SHA-2, each replacing a predecessor whose collision resistance had fallen. The other axis is diversification: SHA-2 and SHA-3 are kept alive together, deliberately, because they fail differently. FIPS 202 calls SHA-3 a "supplement" for exactly this reason [24]. If a structural attack ever lands on the Merkle-Damgard family, SHA-3's sponge is a ready backup that does not share the same skeleton -- and vice versa. You do not keep a spare tire because the current one is flat. You keep it because someday it might be.

The wart SHA-2 still carries

The clearest reason to hold a structurally different backup is a flaw SHA-2 inherited from the whole Merkle-Damgard family, one that is not a collision attack at all.

Length-extension attack

Given only a digest H(m) and the length of m -- but not m itself -- an attacker can compute H(m || padding || s) for a suffix s of their choosing. A Merkle-Damgard digest is simply the function's internal state after the last block, so it hands the attacker the exact starting point needed to keep hashing.

This is why H(secret || message) is a broken message-authentication code: an attacker who sees one valid tag can append data and forge a new valid tag without knowing the secret. It is the specific reason HMAC was designed, and the specific reason cryptographers wrap secrets rather than concatenating them.

Ctrl + scroll to zoom
Merkle-Damgard exposes its full internal state as the digest, enabling length extension. The sponge keeps a hidden capacity, so SHA-3 is immune.

SHA-3's sponge absorbs input into a wide internal state but squeezes out only part of it, keeping a hidden capacity the attacker never sees. That single design choice makes SHA-3 immune to length extension -- the exact Merkle-Damgard wart SHA-2 still carries [24]. Diversification is not sentiment; it is holding one primitive that is missing a specific weakness of the other.

The wider field

Beyond the two NIST standards sit fast, non-NIST alternatives worth naming, though their internals belong to a dedicated hash field guide. BLAKE2 and BLAKE3 are fast, length-extension-immune designs; BLAKE3 is built as an internal Merkle tree and markets itself as much faster than MD5, SHA-1, SHA-2, SHA-3, and BLAKE2 while being "secure against length extension, unlike SHA-2" [29, 30]. KangarooTwelve is a Keccak-based extendable-output function tuned for raw speed [31]. None of these is a migration requirement; they are options where speed matters more than a FIPS stamp.

PrimitiveConstructionCollision securityLength extensionWhere it fits
SHA-256Merkle-Damgard~2^128VulnerableFIPS default, hardware-accelerated
SHA3-256Sponge (Keccak)~2^128ImmuneFIPS supplement, structural diversity
BLAKE3Internal Merkle tree~2^128ImmuneFastest, non-FIPS
KT128 (KangarooTwelve)Sponge XOF~2^128ImmuneKeccak-based speed leader
SHA-1 (baseline)Merkle-DamgardBroken in practiceVulnerableDo not use for new work

So the successors are safe, and the boundary between them is clear. Does that mean MD5 and SHA-1 are simply "broken," full stop? Both halves of that sentence are more subtle than they sound.

8. What "Broken" Actually Means

"MD5 and SHA-1 are broken" is one of the most repeated sentences in security, and one of the most imprecise. Broken for what? The honest answer is both narrower and deeper than the slogan, and getting it right is the difference between a competent migration and a superstitious one.

Start with the ceiling. The birthday bound is not merely the best attack anyone has found; by an elementary counting argument in the black-box model, no collision search on an n-bit hash can do better than about 2n/22^{n/2}. That is a proven floor on the work, so when we say a hash "fell," we mean an attack got below even that reduced barrier -- SHA-1's collisions cost roughly 2632^{63} against a 2802^{80} bound. The bound held as a concept; the specific functions failed to meet it.

Now the narrowing. Defeating collision resistance says nothing about the other two promises. MD5 and SHA-1 preimage resistance remains largely intact: you still cannot, in practice, take a SHA-1 digest and find any message that produces it, because that attack costs the full 21602^{160} [28]. Every collision in this article had the attacker choosing both sides. None of them inverted a hash. So a password stored as a salted SHA-1 hash is weak for many reasons, but not because SHA-1 collided.

The HMAC carve-out is a theorem

The sharpest example of scoping is HMAC, and it is worth stating precisely because it is so often waved away as folklore.

HMAC

A keyed message-authentication code built from a plain hash function by nesting the key through two hash passes: hash the key (xored with one constant) together with the message, then hash the key (xored with a second constant) together with that result. Its security rests on the hash's compression function behaving like a pseudorandom function, not on collision resistance.

That single carve-out rescues an enormous amount of deployed infrastructure, and it is why blanket advice to "purge every SHA-1 from the network" is wrong. The keyed uses stand on ground the collision attacks never touched.

How much margin do the successors have?

If the predecessors fell far below their bounds, how close is SHA-2 to its own cliff? Not close. The best public collision results against SHA-256 are all heavily round-reduced: the strongest practical result is a 39-step semi-free-start collision, which improved a 38-step result from 2013, against SHA-256's full 64 steps [34]. A semi-free-start attack even grants the attacker extra freedom over the initial value that a real deployment never allows. In other words, nobody has a practical collision on anything close to full-round SHA-256, from a fixed IV or otherwise. The successor sits comfortably at its theoretical ceiling.

Quantum honesty

Does quantum computing change the verdict? Less than headlines imply. Grover's algorithm speeds up preimage search quadratically, which merely halves the exponent: a quantum attacker brings SHA-256 preimage resistance from 22562^{256} down to about 21282^{128}, which is still infeasible [35]. For collisions, the picture is worse for the attacker than the naive story suggests -- once you honestly account for the memory and hardware cost of the quantum collision algorithms, there is no clean quadratic win over classical collision search [36]. Quantum does not move a well-sized hash from safe to broken.

"Broken" is scoped. Collision resistance fell; preimage resistance and HMAC-SHA-1 did not. The problem is narrower than the slogan -- and, at the same time, deeper, because the entire MD family shares one construction.

And the depth is the twist. The trouble was never only that two specific functions collided. The whole Merkle-Damgard family carries structural liabilities that are features of the design, not bugs in a particular hash: length extension, and Kelsey-Schneier long-message second-preimage attacks that beat the 2n2^n ideal for very long messages [37]. Those are exactly why SHA-3's sponge exists and why the successors coexist by diversification. The real problem was never "swap the algorithm." It was "retire a construction's fragile clause from billions of deployments, and keep a structurally different backup alive."

Which is precisely why, years after the math was settled, this is still an open problem. The mathematics was fixed. The deployments were not.

9. The Deprecated-but-Still-Live Tail

The math was settled years ago. The deployments were not, and the thesis's own second clause is still an open wound. Where is MD5 or SHA-1 still trusted, right now, as you read this?

Start with the most surprising answer: SHA-1 is still Git's default object format. Every commit hash in most repositories on earth is a SHA-1 digest. Git's transition to SHA-256 is real, carefully engineered, and genuinely underway -- but it is opt-in and staged, exposed through an objectFormat extension and a compatObjectFormat for interoperability, deliberately designed as a "dark launch" so users can gain the new hash without any visible change [38]. The design lets a repository support the new hash before anyone flips the default, which is why the runway is measured in years, not months. That is the opposite of "Git migrated off SHA-1." Git added collision detection with sha1dc, then began a long, optional migration whose default is still the broken hash.

Check which hash your Git repository uses

Run git rev-parse --show-object-format inside a repository. It prints sha1 or sha256. If it prints sha1, every object identifier in that repo is a SHA-1 digest, protected in practice by the sha1dc detection Git ships, not by SHA-1's collision resistance.

Git is only the visible tip. MD5 and SHA-1 persist in embedded firmware that will never be patched, in enterprise PKI islands, in legacy network protocols, and in deduplication systems whose keys are hashes. Each is a place where the primitive fell but the deployment kept trusting it -- the exact two-failure condition, waiting.

The cost curve keeps falling

What makes the tail dangerous is that the price of an attack only drops. Shambles established that "all attacks that are practical on MD5 are now also practical on SHA-1," pushing a chosen-prefix SHA-1 collision to a total compute cost under 100,000 US dollars [16]. That number falls every year as GPUs get cheaper and the cryptanalysis sharpens. A deployment that felt safe because "nobody would spend millions on this" is on a countdown, because soon nobody will need millions.

Honest mathematical limits, too

Not every open question is operational. A few are genuinely mathematical, and honesty requires naming them. How far can collision cryptanalysis climb past the current round-reduced records on SHA-256, whose best practical result still stops well short of full-round from a fixed IV [34]? How much do the structural Merkle-Damgard weaknesses -- length extension, and Kelsey-Schneier long-message second-preimages -- constrain future designs [37]? How far can the round-reduced frontier on SHA-3's own permutation be pushed? These are live research questions, but none of them threatens a correctly deployed SHA-2 or SHA-3 today.

The center of gravity, though, is not in a lab. It is operational: how do you retire a primitive from billions of interlocking dependencies before the next drop in attack cost reaches the ones you forgot about? That is not a question cryptography can answer. It is a question of inventory, prioritization, and follow-through -- which is exactly what a practitioner can act on. So what do you actually do on Monday morning?

10. Auditing and Migrating Today

You can compress this entire history into a single audit question and carry it into any codebase:

That question sorts every hash use cleanly, because it asks the one thing the four breaks all had in common: an attacker who controlled both colliding messages and gained something from the collision.

Migrate these now, because they are collision-dependent: X.509 certificates, digital signatures of every kind, code signing, content-addressed storage keys such as Git and Subversion object identifiers, and any adversarial deduplication where a hash decides that two objects are "the same."

You can generally leave these, because collision resistance is not what protects them: HMAC-SHA-1 and HMAC-MD5, which rest on a pseudorandom-function assumption instead [33]; non-adversarial checksums that guard against accidental corruption rather than a motivated forger; and verification of already-trusted legacy data where no attacker chooses the inputs [28]. NIST's own guidance keeps SHA-1 available for HMAC and key derivation for exactly this reason.

JavaScript A collision-dependent-use auditor
function auditHashUse(use) {
const collisionDependent = [
  "certificate", "signature", "code-signing",
  "git-object", "content-address", "dedup-key"
];
const safe = ["hmac", "checksum", "legacy-verify", "kdf"];

if (collisionDependent.includes(use)) {
  return "MIGRATE -- collision-dependent, move to SHA-2 or SHA-3";
}
if (safe.includes(use)) {
  return "OK -- collision resistance is not relied on";
}
return "REVIEW -- ask: can an adversary supply both inputs and profit?";
}

["certificate", "hmac", "git-object", "checksum", "code-signing"].forEach(function (u) {
console.log(u, "->", auditHashUse(u));
});

Press Run to execute.

Choosing a target

Once you know a use must move, pick the destination by requirement, not by fashion. SHA-256 is the FIPS default and the safe first answer: NIST tells designers to implement it at a minimum, and it is hardware-accelerated on modern CPUs [23, 28]. Want length-extension resistance for free? SHA-512/256 truncates a wider computation and never leaks its full state [23]. Want structural diversity or an extendable-output function? Reach for SHA-3 or SHAKE [24].

If raw speed dominates and a FIPS stamp is not required, BLAKE3 is the fastest of the group and length-extension-immune [30]. And if you are stuck on a SHA-1 you cannot rip out this quarter, deploy sha1dc collision detection the way Git did, then schedule the real migration behind it [27].

The mistakes, mapped to the breaks

Every common hashing mistake is a small echo of one of the four incidents. Naming the echo makes the fix obvious.

The mistakeThe break it echoesThe fix
MD5 or SHA-1 for certificates or code signingRogue CA (2008), Flame (2012)SHA-256 signatures [23]
SHA-1 as a content-address or dedup keySHATTERED (2017)SHA-256 objects, sha1dc as a stopgap [27]
SHA-1 for identity or Web-of-Trust signaturesShambles (2020), CVE-2019-14855Modern GnuPG on SHA-256 [16]
H(secret || message) used as a MACLength extensionHMAC, or KMAC on SHA-3 [33]
Assuming a collision break means a preimage break--Keep salted preimage and HMAC uses; migrate only collision-dependent ones [28]

Two pitfalls deserve their own warning because they masquerade as fixes. Swapping Ethereum's Keccak-256 for standardized SHA3-256 silently changes your digests [24]. And treating sha1dc as a migration rather than a stopgap leaves you permanently one clever attack away from trouble; detection buys time, it does not end the dependency.

Internalize that audit question and these habits, and you have absorbed the base rate this whole history was written to establish. It remains only to name it.

11. The Base Rate

Return to the digest from the opening: 38762cf7f55934b34d179ae6a4c80cadccbb7f0a. You can read it now. It is a SHA-1 value shared by two different PDFs -- an identical-prefix collision from SHATTERED, which means it proved SHA-1 dead for content addressing but could not, on its own, forge a certificate for a chosen identity [5]. That one artifact contains the whole argument in miniature: a real mathematical break, precisely scoped, whose damage depended entirely on what still trusted it.

Stretch that artifact across nearly four decades. From MD5's publication in 1992 to the federally mandated retirement of its successor SHA-1 in 2030 is a thirty-eight-year empirical record [6, 26]. Inside it sit four undisputed, reproducible, weaponized breaks -- the 2008 rogue CA, 2012's Flame, 2017's SHATTERED, 2020's Shambles. Four in twelve years, on two primitives that fell the same way, is not a scare story. It is a measured base rate, and it is the entire justification for migrating to SHA-2 and SHA-3.

Every break in this story needed two failures at once: a hash whose math had fallen, and a deployment that had not yet stopped trusting it.

That is how this article honors the series' thesis without lying about the mathematics. This is the one topic where the primitive genuinely fell -- and even here, cryptanalysis was necessary and never sufficient. RapidSSL had to still be signing with MD5. Microsoft's licensing PKI had to still be signing with MD5. GnuPG had to still default to SHA-1. The math was the loaded chamber; the still-live deployment pulled the trigger.

And keep the boundary honest, because the slogan overreaches in both directions. "Broken" is scoped to collision-dependent uses: HMAC-SHA-1 survives on a proof, and preimage resistance held [33, 28]. The successors do not stand in a line of succession at all -- SHA-2 and SHA-3 coexist by diversification, one construction covering the other's structural blind spot.

For the mechanisms of how the successors themselves could someday be attacked -- Merkle-Damgard collisions, length extension, and the sponge's algebraic frontier -- see the structural sibling to this piece, How SHA-2 and SHA-3 Would Break, along with the series' dedicated hash and X.509/PKI field guides. The migration itself is not a debate. It is an argument the evidence already won. The only open question left is how fast the still-live tail catches up before the next drop in attack cost reaches the systems that forgot to.

12. Frequently Asked Questions

Frequently asked questions

Is SHA-1 broken?

Yes, for collision-dependent uses such as signatures and certificates, where its collision resistance has fallen far below the birthday bound. No, for its other promises: SHA-1 preimage resistance remains intact, and HMAC-SHA-1 is not broken by any collision attack [33, 28]. "Broken" is a statement about one property, not the whole function.

Is SHATTERED the same thing as Shambles?

No, and the difference is the whole game. SHATTERED (2017) is an identical-prefix collision: it proved SHA-1 dead for content addressing but cannot forge a chosen identity [5]. Shambles (2020) is a chosen-prefix collision: strictly more powerful, and the capability that actually forges certificates and impersonates identities [16].

Did Git move off SHA-1?

No. Git added sha1dc collision detection and an opt-in SHA-256 object format, but SHA-1 is still the default object format for most repositories [27, 38]. The transition is staged and largely unfinished; do not assume your repository has migrated.

Is HMAC-SHA-1 safe to keep using?

Yes. HMAC's security reduces to the compression function acting as a pseudorandom function, not to collision resistance, so the collision attacks in this article do not apply. RFC 2104 stated this in 1997, and later proofs formalized it [33]. You do not need to rip HMAC-SHA-1 out on account of SHATTERED or Shambles.

Does hashing twice or concatenating MD5 and SHA-1 make it stronger?

No. Antoine Joux showed in 2004 that multicollisions in iterated hashes make a concatenation only about as strong as its stronger component, not the sum of the two [39]. Cascading broken hashes is a dead end; migrate to a single strong hash instead.

Is Ethereum's Keccak-256 the same as SHA3-256?

No. Ethereum uses the original Keccak padding, finalized before FIPS 202 changed the padding rule for standardized SHA-3. The two produce different digests for the same input, so the libraries are not interchangeable [24].

Can I still use MD5 or SHA-1 for anything?

Yes, but narrowly. Non-adversarial checksums that detect accidental corruption, HMAC, key derivation, and verification of already-trusted legacy data are all acceptable, because none relies on an adversary being unable to find a collision [28]. Never use either for a new signature, certificate, or code-signing operation.

Study guide

Key terms

Collision resistance
The infeasibility of finding any two messages that share a digest. The fragile promise that fell for MD5 and SHA-1.
Birthday bound
Collision work is about 2 to the n over 2, not 2 to the n, so a 160-bit hash offers only 80-bit collision security.
Identical-prefix collision
Two near-twin messages that share a prefix and one digest. Breaks content addressing but cannot forge a chosen identity.
Chosen-prefix collision
Two different attacker-chosen prefixes driven to one digest. The hinge capability that turns a collision into a forgery.
Merkle-Damgard construction
The iterated compression design shared by MD5, SHA-1, and SHA-2, which also carries length extension as a structural liability.
HMAC
A keyed authenticator whose security rests on a pseudorandom-function assumption, not collision resistance, so HMAC-SHA-1 remains safe.

Comprehension questions

  1. Why did a working MD5 collision in 2004 not immediately forge certificates?

    It was an identical-prefix collision, which cannot encode two different chosen identities. Forgery needed the chosen-prefix capability from 2007.

  2. What were the two failures behind every breach in this article?

    A hash whose collision resistance had already fallen, and a deployment that still trusted it, such as RapidSSL, Microsoft's licensing PKI, or GnuPG 1.4.

  3. Why do SHA-2 and SHA-3 both exist if neither is broken?

    Diversification. SHA-3's sponge fails differently from Merkle-Damgard and is immune to length extension, so it is a structurally different backup.

  4. Is HMAC-SHA-1 affected by SHATTERED or Shambles?

    No. HMAC does not rely on collision resistance, so those collision attacks do not compromise it.

References

  1. Alexander Gostev (2012). Gadget in the Middle: Flame Malware Spreading Vector Identified (Securelist, Kaspersky Lab). https://securelist.com/gadget-in-the-middle-flame-malware-spreading-vector-identified/33081/
  2. Xiaoyun Wang, Dengguo Feng, Xuejia Lai, & Hongbo Yu (2004). Collisions for Hash Functions MD4, MD5, HAVAL-128 and RIPEMD. https://eprint.iacr.org/2004/199
  3. Marc Stevens (2013). Counter-cryptanalysis (CRYPTO 2013). https://marc-stevens.nl/research/papers/C13-S.pdf
  4. Microsoft (2012). Microsoft Security Advisory 2718704: Unauthorized Digital Certificates Could Allow Spoofing. https://learn.microsoft.com/en-us/security-updates/securityadvisories/2012/2718704
  5. Marc Stevens, Elie Bursztein, Pierre Karpman, Ange Albertini, & Yarik Markov (2017). SHAttered: The First Collision for Full SHA-1. https://shattered.io/
  6. Ronald Rivest (1992). The MD5 Message-Digest Algorithm (RFC 1321). https://datatracker.ietf.org/doc/html/rfc1321
  7. NIST (1995). FIPS 180-1: Secure Hash Standard. https://csrc.nist.gov/pubs/fips/180-1/final
  8. Bert den Boer & Antoon Bosselaers (1993). Collisions for the Compression Function of MD5. https://doi.org/10.1007/3-540-48285-7_26
  9. Hans Dobbertin (1996). Cryptanalysis of MD5 Compress (CryptoBytes 2(2), rump session).
  10. Florent Chabaud & Antoine Joux (1998). Differential Collisions in SHA-0. https://doi.org/10.1007/BFb0055720
  11. Xiaoyun Wang & Hongbo Yu (2005). How to Break MD5 and Other Hash Functions. https://doi.org/10.1007/11426639_2
  12. Xiaoyun Wang, Yiqun Lisa Yin, & Hongbo Yu (2005). Finding Collisions in the Full SHA-1. https://doi.org/10.1007/11535218_2
  13. Marc Stevens, Arjen Lenstra, & Benne de Weger (2007). Chosen-Prefix Collisions for MD5 and Colliding X.509 Certificates for Different Identities (EUROCRYPT 2007). https://marc-stevens.nl/research/
  14. Marc Stevens (2021). A Survey of Chosen-Prefix Collision Attacks (Computational Cryptography, Cambridge University Press). https://marc-stevens.nl/research/
  15. Marc Stevens, Pierre Karpman, & Thomas Peyrin (2016). Freestart Collision for Full SHA-1 (EUROCRYPT 2016). https://marc-stevens.nl/research/
  16. Gaetan Leurent & Thomas Peyrin (2020). SHA-1 is a Shambles: First Chosen-Prefix Collision on SHA-1. https://sha-mbles.github.io/
  17. Alexander Sotirov, Marc Stevens, & Jacob Appelbaum (2008). MD5 Considered Harmful Today (25C3). https://marc-stevens.nl/research/hashclash/rogue-ca/
  18. Alexander Sotirov, Marc Stevens, Jacob Appelbaum, Arjen Lenstra, David Molnar, Dag Arne Osvik, & Benne de Weger (2009). Creating a Rogue CA Certificate (HashClash rogue-CA project). https://marc-stevens.nl/research/hashclash/rogue-ca/
  19. Max Fillinger & Marc Stevens (2015). Reverse-Engineering of the Cryptanalytic Attack Used in the Flame Super-Malware (ASIACRYPT 2015). https://marc-stevens.nl/research/
  20. Marc Stevens (2012). Attacks on Hash Functions and Applications (PhD thesis, Leiden University). https://marc-stevens.nl/research/
  21. Fox-IT (2012). Black Tulip: Report of the Investigation into the DigiNotar Certificate Authority Breach. http://web.archive.org/web/20170618021335/https://www.rijksoverheid.nl/binaries/rijksoverheid/documenten/rapporten/2012/08/13/black-tulip-update/black-tulip-update.pdf
  22. Gaetan Leurent & Thomas Peyrin (2020). SHA-1 is a Shambles (USENIX Security 2020). https://www.usenix.org/conference/usenixsecurity20/presentation/leurent
  23. NIST (2015). FIPS 180-4: Secure Hash Standard (SHS). https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
  24. NIST (2015). FIPS 202: SHA-3 Standard -- Permutation-Based Hash and Extendable-Output Functions. https://csrc.nist.gov/pubs/fips/202/final
  25. Elaine Barker & Allen Roginsky (2019). NIST SP 800-131A Rev. 2: Transitioning the Use of Cryptographic Algorithms and Key Lengths. https://csrc.nist.gov/pubs/sp/800/131/a/r2/final
  26. NIST (2022). NIST Retires SHA-1 Cryptographic Algorithm. https://www.nist.gov/news-events/news/2022/12/nist-retires-sha-1-cryptographic-algorithm
  27. Marc Stevens & Dan Shumow (2017). sha1collisiondetection: Hardened SHA-1 Collision Detection. https://github.com/cr-marcstevens/sha1collisiondetection
  28. NIST (2015). NIST Policy on Hash Functions. https://csrc.nist.gov/Projects/Hash-Functions/NIST-Policy-on-Hash-Functions
  29. Markku-Juhani Saarinen & Jean-Philippe Aumasson (2015). The BLAKE2 Cryptographic Hash and Message Authentication Code (RFC 7693). https://datatracker.ietf.org/doc/html/rfc7693
  30. Jack OConnor, Jean-Philippe Aumasson, Samuel Neves, & Zooko Wilcox-OHearn (2020). BLAKE3: One Function, Fast Everywhere. https://github.com/BLAKE3-team/BLAKE3
  31. Keccak Team (2016). KangarooTwelve and TurboSHAKE. https://keccak.team/kangarootwelve.html
  32. Mihir Bellare (2006). New Proofs for NMAC and HMAC: Security without Collision Resistance. https://doi.org/10.1007/s00145-014-9185-x
  33. Hugo Krawczyk, Mihir Bellare, & Ran Canetti (1997). HMAC: Keyed-Hashing for Message Authentication (RFC 2104). https://datatracker.ietf.org/doc/html/rfc2104
  34. Yingxin Li, Fukang Liu, & Gaoli Wang (2024). New Records in Collision Attacks on SHA-2 (IACR ePrint 2024/349). https://eprint.iacr.org/2024/349
  35. Lily Chen, Stephen Jordan, Yi-Kai Liu, Dustin Moody, Rene Peralta, Ray Perlner, & Daniel Smith-Tone (2016). NISTIR 8105: Report on Post-Quantum Cryptography. https://csrc.nist.gov/pubs/ir/8105/final
  36. Daniel J. Bernstein (2009). Cost Analysis of Hash Collisions: Will Quantum Computers Make SHARCS Obsolete?. https://cr.yp.to/hash/collisioncost-20090823.pdf
  37. John Kelsey & Bruce Schneier (2005). Second Preimages on n-Bit Hash Functions for Much Less than 2^n Work. https://doi.org/10.1007/11426639_28
  38. Git Project (2020). Git Hash Function Transition. https://git-scm.com/docs/hash-function-transition
  39. Antoine Joux (2004). Multicollisions in Iterated Hash Functions. Application to Cascaded Constructions. https://doi.org/10.1007/978-3-540-28628-8_19