<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Parag Mali - tag: hash-functions</title><description>Posts tagged hash-functions.</description><link>https://paragmali.com/</link><language>en-US</language><lastBuildDate>Sun, 19 Jul 2026 05:08:43 GMT</lastBuildDate><atom:link href="https://paragmali.com/tags/hash-functions/rss.xml" rel="self" type="application/rss+xml"/><item><title>How SHA-2 and SHA-3 Would Break: Merkle-Damgard Collisions, Length Extension, and the Sponge&apos;s Algebraic Frontier</title><link>https://paragmali.com/blog/how-sha-2-and-sha-3-would-break-merkle-damgard-collisions-le/</link><guid isPermaLink="true">https://paragmali.com/blog/how-sha-2-and-sha-3-would-break-merkle-damgard-collisions-le/</guid><description>SHA-2 and SHA-3 have never broken, yet each construction already dictates how it would fall -- collisions, length extension, and the sponge algebraic frontier.</description><pubDate>Fri, 17 Jul 2026 00:00:00 GMT</pubDate><content:encoded>
SHA-256 and SHA3-256 make the same promise -- about $2^{128}$ work to force a collision -- yet they share almost none of their internal machinery, and that difference decides how each one would die. SHA-2 (Merkle-Damgard) would fall to a Wang-style differential collision threaded through its compression function, and it already carries the length-extension property by design. SHA-3 (the Keccak sponge) has neither weakness; it relocates the fight onto the algebra of a single degree-2 step, chi, where the leading avenues are cube-style algebraic attacks and internal-differential collisions. The best published attacks reach only about 39 of SHA-256&apos;s 64 steps and 6 of Keccak&apos;s 24 rounds, so both margins are very large today. This is a structural &quot;how it would break,&quot; not a report that either has.
&lt;h2&gt;1. Two Hashes, Two Deaths&lt;/h2&gt;
&lt;p&gt;Here is something you can say about a machine before it has ever failed: which way it will fall. A structural engineer knows a bridge sways before it buckles and buckles before it snaps, because the failure mode is written into the truss, not painted onto the surface. &lt;a href=&quot;https://paragmali.com/blog/the-fingerprint-two-files-shared-a-field-guide-to-cryptograp/&quot; rel=&quot;noopener&quot;&gt;Cryptographic hash functions&lt;/a&gt; are the same. We can already describe, mechanically and in detail, how SHA-2 and SHA-3 would break -- even though nobody has ever broken either one, and the two descriptions have almost nothing in common.&lt;/p&gt;
&lt;p&gt;The two functions NIST standardized as the Secure Hash Standard and the SHA-3 Standard [@fips-180-4, @fips-202] sit underneath an enormous amount of modern security: certificate chains, signed software updates, commitment schemes, the proof-of-work in a blockchain. They advertise the same guarantee. For a 256-bit digest, finding any two inputs that hash to the same value should cost about $2^{128}$ attempts.That number is easy to say and hard to feel. $2^{128} \approx 3.4 \times 10^{38}$, a 39-digit count -- far more than every grain of sand on Earth, yet far fewer than the atoms that make up the Earth. It is an enormous human-scale number that is still dwarfed by atomic-scale ones.&lt;/p&gt;

A hash function is collision resistant if it is computationally infeasible to find two distinct inputs $m_1 \neq m_2$ with $H(m_1) = H(m_2)$. It is the strongest of the standard hash guarantees, and the one that differential cryptanalysis attacks head-on.
&lt;p&gt;That $2^{128}$ figure is not a design target so much as a ceiling imposed by arithmetic. Feed roughly $2^{n/2}$ random messages into any $n$-bit hash and, by the birthday paradox, two of them almost certainly collide. So $2^{128}$ is simply the generic cost of a birthday search against a 256-bit digest -- the number every genuine attack has to beat to count as a break [@fips-180-4].&lt;/p&gt;

For an ideal $n$-bit hash, a collision can always be found in about $2^{n/2}$ evaluations by the birthday paradox, and a preimage in about $2^{n}$. These generic costs -- $2^{128}$ and $2^{256}$ for a 256-bit digest -- are the definitional security targets any structural attack must beat.
&lt;p&gt;Now the strange part. SHA-256 and SHA3-256 keep that identical promise using almost none of the same parts. SHA-2 iterates a small compression function from a fixed starting value, folding the message in one block at a time -- the Merkle-Damgard design. SHA-3 does something else entirely: it stirs the message into a large public permutation and squeezes the digest back out -- the sponge. Two constructions, one guarantee.&lt;/p&gt;
&lt;p&gt;And because the constructions differ, their deaths differ. A Merkle-Damgard hash does not die at its digest size; it dies when a carefully chosen difference in the input threads through the compression function and cancels at the output -- the method that felled MD5 and SHA-1. It also leaks: given a digest, you can often extend the message without knowing it. The sponge has neither trait. It hands an attacker a different target: the algebra of its one nonlinear step, chi, which has algebraic degree just two.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Construction, not digest size, decides the failure mode. SHA-2 would die by a differential collision on its compression function and carries length extension by design; SHA-3 exposes an algebraic frontier against its degree-2 chi and has no length extension. Same promise, different battlefield.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is the whole argument in one sentence, and the rest of this article is its proof. One boundary before we begin.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This is structural cryptanalysis: it studies attacks on the mathematics of the algorithms themselves. Side-channel leaks, fault and power attacks, buggy implementations, weak random number generators, and protocol misuse are out of scope. They are real, and they are the subject of the companion article, &quot;How the Hash Functions Broke in Real Life: MD5, Flame, SHATTERED, and the Long Death of SHA-1.&quot; When the practical SHA-1 collisions appear below, they appear only as proof that a method works end to end, never as deployment history.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To see why each death is pre-written, we have to go back to the 1989 bargain that made iterated hashing trustworthy in the first place -- and to the two debts it quietly signed on SHA-2&apos;s behalf.&lt;/p&gt;
&lt;h2&gt;2. The Merkle-Damgard Bargain of 1989&lt;/h2&gt;
&lt;p&gt;In 1989 two people, an ocean apart and unaware of each other, answered the same question the same way -- and in doing so pre-wrote how SHA-2 would one day die. Ralph Merkle and Ivan Damgard each presented the result at CRYPTO 1989 [@merkle-1989, @damgard-1989].&lt;/p&gt;
&lt;p&gt;The question was practical and deep at once: how do you hash a message of &lt;em&gt;arbitrary&lt;/em&gt; length using only a &lt;em&gt;fixed-size&lt;/em&gt; building block, and then &lt;em&gt;prove&lt;/em&gt; the result is as hard to collide as that block? Their answer is the scaffolding under nearly every hash you have ever used.&lt;/p&gt;

A method for turning a fixed-input-length compression function $f$ into a hash on arbitrary-length messages. Pad the message and split it into blocks $M_1, M_2, \ldots, M_t$; starting from a fixed initialization value $H_0 = IV$, compute $H_i = f(H_{i-1}, M_i)$; output the final $H_t$ as the digest. Merkle and Damgard each proved that if $f$ is collision resistant, so is the whole hash.
&lt;p&gt;The shape of the compression function they had in mind, and the one every hash in the SHA line uses, is Davies-Meyer.&lt;/p&gt;

A way to build a compression function from a block cipher $E$: treat the message block as the key and the chaining value as the plaintext, then feed the input back in, $H_i = E_{M_i}(H_{i-1}) \oplus H_{i-1}$. The final XOR -- the &quot;feed-forward&quot; -- is what makes the function hard to invert; without it, an attacker could run the cipher backward from a chaining value.

flowchart LR
    IV[&quot;IV (fixed start)&quot;] --&amp;gt; F1[&quot;f&quot;]
    B1[&quot;Message block 1&quot;] --&amp;gt; F1
    F1 --&amp;gt;|&quot;chaining value H1&quot;| F2[&quot;f&quot;]
    B2[&quot;Message block 2&quot;] --&amp;gt; F2
    F2 --&amp;gt;|&quot;chaining value H2&quot;| F3[&quot;f&quot;]
    B3[&quot;Final block + length pad&quot;] --&amp;gt; F3
    F3 --&amp;gt; D[&quot;Digest = final chaining value&quot;]
&lt;p&gt;The proof is the reason the world trusted this design for two decades, and it is worth seeing rather than taking on faith -- because both of SHA-2&apos;s structural debts fall directly out of it.&lt;/p&gt;

Suppose an attacker finds two different messages $M \neq M&apos;$ with $H(M) = H(M&apos;)$; the two chains therefore end on the same value, $H_t = H&apos;_{t&apos;}$. If the messages have different lengths, Merkle-Damgard strengthening (appending the encoded length) forces the final blocks to differ, so two *different* last-step inputs map under $f$ to the *same* output -- a collision in $f$. If the messages have the same length, walk backward from the output, comparing the inputs fed into each $f$-call. The outputs match at the last step; if the inputs there differ, that is your $f$-collision, and if they match, the previous chaining values must match too, so you recurse one step earlier. Because $M \neq M&apos;$, some block differs, so the backward march cannot stay equal all the way down -- at the first step (scanning from the end) where the two $f$-inputs diverge, two distinct inputs produce one output. Every collision of $H$ yields a collision of $f$. Contrapositively, if $f$ is collision resistant, so is $H$: the whole hash is at least as strong as its compression function [@merkle-1989, @hac-chap9].
&lt;p&gt;That reduction is a genuine gift -- it lets designers focus all their effort on one small function -- but it comes with two debts written into the same clause.&lt;/p&gt;
&lt;p&gt;The first debt: &lt;em&gt;all&lt;/em&gt; of the hash&apos;s collision resistance now concentrates in $f$. An attacker cannot collide SHA-256 without colliding its 64-step compression function, so that function is the entire battlefield. Everything a would-be attacker does, and everything the last thirty-five years of cryptanalysis has done, targets exactly that object [@hac-chap9].&lt;/p&gt;
&lt;p&gt;The second debt is subtler and, for a practitioner, more immediately dangerous. Look again at the chain: the digest that comes out &lt;em&gt;is&lt;/em&gt; the final chaining value -- the complete internal state at the end of the computation. Nothing is hidden.&lt;/p&gt;

Given only $H(m)$ and the length of $m$ -- but not $m$ itself -- an attacker can compute $H(m \,\|\, \text{pad} \,\|\, y)$ for a suffix $y$ of their choosing. Because the digest is the full internal state, the attacker simply resumes the iteration from it, appends the &quot;glue&quot; padding, and continues hashing. This works against any plain Merkle-Damgard hash, including SHA-256.
&lt;p&gt;The strengthening step -- appending the message length before the final block -- is what makes the collision proof go through, closing the length-mismatch case above.The Davies-Meyer feed-forward and the length padding are two separate load-bearing details. The feed-forward stops an attacker running the block cipher backward from a chaining value; the length padding stops trivial collisions between messages of different lengths. Remove either and the reduction fails. But it does nothing to hide the state -- so it fixes the first debt&apos;s proof without touching the second debt at all.&lt;/p&gt;

Merkle-Damgard signs two debts at once: all collision resistance concentrates in one small function, and the digest is the whole internal state. The first is where the hash can be collided; the second is why it leaks.
&lt;p&gt;A construction that concentrates all its collision resistance in one small function is only ever as safe as that function is hard to collide. For fifteen years, nobody could touch it. Then the mathematics of differences arrived, and MD5 fell in minutes.&lt;/p&gt;
&lt;h2&gt;3. How a Merkle-Damgard Hash Actually Dies&lt;/h2&gt;
&lt;p&gt;The break, when it came, did not come from brute force. It came from the arithmetic of differences -- and once you see it, you cannot un-see why SHA-2 is built the way it is.&lt;/p&gt;
&lt;p&gt;The idea starts with a question no birthday search ever asks: what if we do not treat the hash as a black box, but push a &lt;em&gt;specific&lt;/em&gt;, carefully chosen difference between two messages through its internals and watch where the difference travels? If we can arrange for the difference to appear, ripple through a few steps, and then cancel itself out exactly at the output, the two messages collide -- and we never paid the $2^{n/2}$ birthday toll.&lt;/p&gt;
&lt;p&gt;Florian Chabaud and Antoine Joux built the first working version of this against SHA-0 at CRYPTO 1998 [@chabaud-joux-1998]. Their tools were two ideas that still organize the whole subject.&lt;/p&gt;

A low-weight input difference that creates a small perturbation over a handful of steps and then cancels itself, leaving the internal state unchanged afterward. Chaining local collisions along a message is how an attacker assembles a full collision out of small, controllable pieces.

A step-by-step trail specifying the exact difference between two computations at every point in the compression function, chosen so the trail begins with a message difference and ends in zero difference at the output. The probability that a random conforming message pair follows the trail governs the attack&apos;s cost.
&lt;p&gt;By chaining local collisions along a differential characteristic so the total difference vanished at the output, Chabaud and Joux drove the estimated cost of a SHA-0 collision down to roughly $2^{61}$ -- comfortably below the $2^{80}$ birthday wall for a 160-bit digest [@chabaud-joux-1998]. It was an estimate, not a produced collision, but it was the first real crack in the black box.&lt;/p&gt;
&lt;p&gt;Then Xiaoyun Wang turned the estimate into a scalpel. In 2004 and 2005, Wang, with Hongbo Yu and Yiqun Lisa Yin, announced results that stunned the field: full, practical collisions for MD5 -- Rivest&apos;s 1992 design [@rfc-1321] -- and a collision attack on the full SHA-1 [@rfc-3174], well below its birthday bound [@wang-yu-2005, @wang-yin-yu-2005]. The engine had two new parts. First, a &lt;em&gt;hand-built nonlinear path&lt;/em&gt; through the hard early steps of the compression function, spliced onto a cheap linear trail for the rest. Second, and decisive:&lt;/p&gt;

A technique that satisfies the early, high-probability conditions of a differential characteristic *deterministically*, by directly adjusting message words rather than hoping a random pair happens to comply. It moves the expensive part of the search from the beginning of the trail to its cheaper tail, collapsing the total cost.

flowchart TD
    A[&quot;Choose a message difference&quot;] --&amp;gt; B[&quot;Build a differential characteristic ending in zero output difference&quot;]
    B --&amp;gt; C[&quot;Derive per-step sufficient conditions on state bits&quot;]
    C --&amp;gt; D[&quot;Message-modify the early steps to force cheap conditions deterministically&quot;]
    D --&amp;gt; E[&quot;Search the residual probability for the hard late conditions&quot;]
    E --&amp;gt; F[&quot;Output a conforming colliding message pair&quot;]
&lt;p&gt;Why does modifying the message help so much? The answer is specific enough to work through, and it is exactly the mechanism the earlier hashes handed the attacker for free.&lt;/p&gt;

In a Davies-Meyer compression function the first sixteen steps consume the sixteen message words of the block essentially one per step: at step $i$ (for $i = 0..15$) the expanded word is just $W_i = m_i$, mixed straight into the state. So each early-step word is a *free variable the attacker fully controls*, entering the computation at exactly one known step.&lt;p&gt;Now, a differential characteristic holds only if certain state bits take certain values at each step -- Wang&apos;s &quot;sufficient conditions.&quot; Left to chance, each condition holds with probability about $1/2$, so a path with $k$ conditions costs about $2^k$ to satisfy by random trial. That is the naive price.&lt;/p&gt;
&lt;p&gt;Here is the trick. Because the attacker controls the very word $m_i$ feeding step $i$, they do not &lt;em&gt;gamble&lt;/em&gt; on the step-$i$ conditions -- they &lt;em&gt;solve&lt;/em&gt; for them. Given the desired output bits of step $i$, invert the round update (its additions, rotations, and Boolean function) for the single unknown $m_i$ and set it to the one value that forces those conditions with probability $1$. Every condition in the first sixteen steps is paid off deterministically, at unit cost, instead of probabilistically at $2^k$.&lt;/p&gt;
&lt;p&gt;Past step sixteen the message words re-enter through the schedule and no longer offer a fresh free variable per step, so the later conditions cannot all be solved directly. Wang&apos;s &lt;em&gt;multi-message&lt;/em&gt; modification clears some of them with coordinated corrective tweaks to several early words, but the residual conditions in the &quot;tail&quot; stay probabilistic. The total cost therefore collapses from the full characteristic probability (all conditions) to just the &lt;em&gt;tail&lt;/em&gt; probability. That collapse is why full MD5 fell in seconds to minutes and full SHA-1 fell to roughly $2^{69}$, far below its $2^{80}$ birthday wall [@wang-yu-2005, @wang-yin-yu-2005].
&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The consequence reset every intuition about hash security. Full MD5, whose 128-bit digest nominally promised $2^{64}$ collision work, collapsed to seconds on a PC [@wang-yu-2005]. Full SHA-1, nominally $2^{80}$, fell to an estimated $2^{69}$ -- a real break of the design, years before anyone spent the compute to exhibit an actual colliding pair [@wang-yin-yu-2005].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; A Merkle-Damgard hash does not die at its digest size. It dies when a differential characteristic plus message modification threads its compression function -- deterministically through the early steps, cheaply through the tail. Collision resistance was never really about the number of output bits; it was always about whether a path exists through $f$.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Those hand-built attacks were later paid out in full, practical collisions -- SHAttered in 2017 and SHAmbles in 2020 -- but those belong to the deployment story, not this one.SHAttered (Stevens, Karpman, Bursztein, Albertini, and Markov) produced the first identical-prefix SHA-1 collision at about $2^{63.1}$ [@shattered]; SHAmbles (Gaetan Leurent and Thomas Peyrin, correcting a common misattribution to Marc Stevens) produced the first &lt;em&gt;chosen-prefix&lt;/em&gt; SHA-1 collision at about $2^{63.4}$ and forged a PGP key [@leurent-peyrin-2020, @sha-mbles-site]. Both are evidence that the differential method pays out end to end; the empirical sibling article tells their story.&lt;/p&gt;
&lt;p&gt;This is the pivotal fact of the whole subject. So the real question becomes: can that same scalpel reach SHA-2? The answer forced cryptography down two roads at once.&lt;/p&gt;
&lt;h2&gt;4. Two Lineages Diverge&lt;/h2&gt;
&lt;p&gt;Start with the cleanest evidence in the whole story that patching a weak compression function only buys time. SHA-0, standardized in 1993, had a linear message expansion; it was withdrawn in 1995 and replaced by SHA-1, whose entire difference from SHA-0 was a &lt;em&gt;single one-bit rotation&lt;/em&gt; added to that expansion. That one rotation held for about a decade. Then a Wang-style path walked straight through it [@wang-yin-yu-2005]. A one-operation fix delayed the break; it did not prevent it.&lt;/p&gt;
&lt;p&gt;This is the pattern to internalize: &quot;just add a round&quot; or &quot;just add a rotation&quot; hardens a Davies-Meyer compression function against yesterday&apos;s specific path, not against the &lt;em&gt;method&lt;/em&gt;. Incremental patches to a lightly-mixed function buy years, not safety -- which is exactly why SHA-2 needed a qualitatively heavier schedule and SHA-3 needed a different construction altogether.&lt;/p&gt;
&lt;p&gt;The full six-generation lineage reads as a slow-motion argument, each break motivating the next design.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Hash family&lt;/th&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Key design idea&lt;/th&gt;
&lt;th&gt;Best collision result&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;MD4&lt;/td&gt;
&lt;td&gt;1990&lt;/td&gt;
&lt;td&gt;Merkle-Damgard + Davies-Meyer, 128-bit, 48 steps&lt;/td&gt;
&lt;td&gt;full collisions (Dobbertin 1996 [@dobbertin-1996]; Wang 2005)&lt;/td&gt;
&lt;td&gt;historical [@wang-yu-2005]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MD5&lt;/td&gt;
&lt;td&gt;1992&lt;/td&gt;
&lt;td&gt;MD4 hardened: 64 steps, per-step constants&lt;/td&gt;
&lt;td&gt;practical full collisions (Wang-Yu 2005)&lt;/td&gt;
&lt;td&gt;historical [@rfc-1321, @wang-yu-2005]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SHA-0&lt;/td&gt;
&lt;td&gt;1993&lt;/td&gt;
&lt;td&gt;160-bit, linear message expansion (no rotation)&lt;/td&gt;
&lt;td&gt;$\approx 2^{61}$ (Chabaud-Joux 1998)&lt;/td&gt;
&lt;td&gt;withdrawn 1995 [@chabaud-joux-1998]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SHA-1&lt;/td&gt;
&lt;td&gt;1995&lt;/td&gt;
&lt;td&gt;SHA-0 plus one-bit rotation, 80 steps&lt;/td&gt;
&lt;td&gt;$\approx 2^{69}$ (Wang 2005); demonstrated 2017&lt;/td&gt;
&lt;td&gt;superseded [@wang-yin-yu-2005, @rfc-3174]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SHA-2&lt;/td&gt;
&lt;td&gt;2001&lt;/td&gt;
&lt;td&gt;bigger state, nonlinear carry-laden schedule, 64/80 steps&lt;/td&gt;
&lt;td&gt;39/64 steps (reduced-round), full unbroken&lt;/td&gt;
&lt;td&gt;active [@fips-180-4, @li-liu-wang-2024]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SHA-3 / Keccak&lt;/td&gt;
&lt;td&gt;2012/2015&lt;/td&gt;
&lt;td&gt;sponge over Keccak-f[1600], 24 rounds, hidden capacity&lt;/td&gt;
&lt;td&gt;6/24 rounds (reduced-round), full unbroken&lt;/td&gt;
&lt;td&gt;active [@fips-202, @keccak-team]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

gantt
    title Two lineages, 1989 to 2024
    dateFormat YYYY
    axisFormat %Y
    section Construction
    Merkle-Damgard bargain :1989, 1990
    MD5 (RFC 1321) :1992, 1993
    SHA-1 (FIPS 180-1) :1995, 1996
    SHA-2 standardized :2001, 2002
    SHA-3 competition :2007, 2012
    SHA-3 standard (FIPS 202) :2015, 2016
    section Cryptanalysis
    Chabaud-Joux on SHA-0 :1998, 1999
    Wang breaks MD5 and SHA-1 :2004, 2006
    Zero-sum full Keccak-f :2011, 2012
    SHA-256 reduced-round records :2013, 2024
    SHA-3 internal-differential records :2013, 2024
&lt;p&gt;By 2005 the field had a decision to make, and it split into two philosophies. The first response was to harden the &lt;em&gt;same&lt;/em&gt; construction. SHA-2, standardized in 2001 and still the workhorse, kept Merkle-Damgard and Davies-Meyer but gave the compression function a much larger state, a heavier message schedule, and modular-addition mixing designed to starve differential paths [@fips-180-4]. That is the road we return to in the next section, because it worked.&lt;/p&gt;
&lt;p&gt;The second response was more radical. Stung by the 2004-2005 breaks, NIST announced the SHA-3 competition on November 2, 2007, and ran it until October 2, 2012, explicitly seeking a hash that would fail &lt;em&gt;differently&lt;/em&gt; from the Merkle-Damgard family -- so that a single new cryptanalytic idea could not bring down every standardized hash at once [@nist-sha3-project]. The winner was Keccak, a sponge built on a large public permutation, designed from the start so that its hidden capacity removes length extension by construction [@keccak-team].&lt;/p&gt;
&lt;p&gt;The subtle and load-bearing point is what NIST did &lt;em&gt;not&lt;/em&gt; do. It did not retire SHA-2.&lt;/p&gt;

The MD5-to-SHA-1-to-SHA-2 progression was a ladder of *replacements* -- each rung was climbed because the one below it broke. SHA-2 and SHA-3 are not that. FIPS 202 states in its own opening that the SHA-3 functions &quot;supplement&quot; SHA-1 and the SHA-2 family rather than replace them [@fips-202], and NIST&apos;s hash-function policy says plainly that &quot;currently there is no need to transition applications from SHA-2 to SHA-3&quot; [@nist-hash-policy]. The two standards coexist on purpose. The value is *diversification*: if a structural idea ever threatens one construction, the other rests on entirely different mathematics and is untouched. SHA-3 is an insurance policy, not an eviction notice.
&lt;p&gt;Two lineages, two answers to the same failure. But an answer is only as good as the attack it survives -- so why has SHA-2 held for more than two decades, and what exactly did the sponge change?&lt;/p&gt;
&lt;h2&gt;5. Why SHA-2 Held, and What the Sponge Changed&lt;/h2&gt;
&lt;p&gt;Two structural facts define the present. The first is that the same message-modification machinery that broke MD5 and SHA-1 &lt;em&gt;stalls&lt;/em&gt; on SHA-2 -- and the reason is one design choice. The second is that the sponge removed the debts a differential attack needs, and put something entirely different in their place.&lt;/p&gt;
&lt;h3&gt;Why the scalpel stalls on SHA-2&lt;/h3&gt;
&lt;p&gt;Recall the mechanism from the last section: message modification is cheap only because, in the early steps, each message word is a free variable entering the state at exactly one place. Break that &quot;one free word per early step&quot; structure and the trick loses its edge. SHA-2 breaks it on purpose.&lt;/p&gt;
&lt;p&gt;In MD5 and SHA-1 the message schedule is essentially a permutation (and, later, a linear expansion) of the input words -- clean and separable. SHA-2&apos;s schedule is neither. From step 16 onward, each expanded word is built by&lt;/p&gt;
&lt;p&gt;$$W_t = \sigma_1(W_{t-2}) + W_{t-7} + \sigma_0(W_{t-15}) + W_{t-16} \pmod{2^{32}}$$&lt;/p&gt;
&lt;p&gt;where $\sigma_0$ and $\sigma_1$ are XORs of rotations and a shift, and the additions are &lt;em&gt;modular&lt;/em&gt; [@fips-180-4]. Those modular additions couple the words through &lt;em&gt;carries&lt;/em&gt;: changing one bit of one word can ripple through carry chains into many others. The clean, separable structure that let an attacker solve each early condition by inverting a single word update is gone. Now solving one sufficient condition perturbs others, and the conditions can no longer be discharged by independent single-word inversion.&lt;/p&gt;
&lt;p&gt;That carry-laden coupling is the structural reason the hand construction that felled MD5 and SHA-1 cannot be driven through SHA-2 by hand at all -- which is why the modern realization of the attack is an automated SAT/SMT solver managing the entangled condition system, and why even that tooling, in the record-holders&apos; own words, &quot;has reached the bottleneck&quot; around 39 of 64 steps [@li-liu-wang-2024]. We return to that number in the next section. For now the point is qualitative: SHA-2 held because it made the compression function&apos;s internals too coupled for the differential scalpel to carve cleanly.&lt;/p&gt;
&lt;h3&gt;What the sponge deleted&lt;/h3&gt;
&lt;p&gt;Keccak does not try to win the differential arms race. It changes the board.&lt;/p&gt;

A hash built from a single large public permutation $f$ over a state of $b = r + c$ bits. To *absorb*, split the padded message into $r$-bit blocks and, for each, XOR it into the first $r$ bits of the state and apply $f$. To *squeeze*, read out $r$ bits at a time, applying $f$ between reads, until enough digest bits are produced. Keccak uses $f = $ Keccak-f[1600], a 1600-bit permutation of 24 rounds.

The sponge state of $b$ bits is split into a *rate* of $r$ bits and a *capacity* of $c$ bits, with $b = r + c$. The message is XORed only into the rate, and the digest is read only from the rate. The capacity is never touched directly by input or output -- it is the hidden reservoir that carries security across the permutation calls.

flowchart LR
    MSG[&quot;Message blocks&quot;] --&amp;gt;|&quot;XOR into rate&quot;| RATE[&quot;Rate (r bits)&quot;]
    RATE --&amp;gt; F[&quot;Keccak-f[1600], 24 rounds&quot;]
    CAP[&quot;Capacity (c bits): never absorbed or squeezed&quot;] --&amp;gt; F
    F --&amp;gt;|&quot;squeeze&quot;| DIG[&quot;Digest, read from the rate only&quot;]
&lt;p&gt;Two debts vanish at once. Because the capacity is never emitted, the digest is &lt;em&gt;not&lt;/em&gt; the full internal state -- so no attacker can resume the computation from it. Length extension is gone by construction, not by patch [@keccak-sponge-duplex]. And because there is no keyed compression function -- just one fixed public permutation -- there is no keyed object to push a differential characteristic through to force a hash collision directly the way Wang did. The entire Merkle-Damgard attack surface is simply absent.&lt;/p&gt;
&lt;p&gt;So what is left to attack? The permutation&apos;s algebra. And that turns on the single nonlinear step inside Keccak-f.&lt;/p&gt;

flowchart LR
    S[&quot;State (1600 bits)&quot;] --&amp;gt; T[&quot;theta: linear column mixing (degree 1)&quot;]
    T --&amp;gt; R[&quot;rho: bit rotations (degree 1)&quot;]
    R --&amp;gt; P[&quot;pi: lane permutation (degree 1)&quot;]
    P --&amp;gt; C[&quot;chi: the only nonlinear step (degree 2)&quot;]
    C --&amp;gt; I[&quot;iota: add round constant (degree 1)&quot;]
    I --&amp;gt; O[&quot;Next-round state&quot;]

Every Boolean function can be written uniquely as a sum (XOR) of monomials over GF(2) -- its algebraic normal form. Its *algebraic degree* is the size of the largest monomial. An affine map (only single-variable terms) has degree 1; an AND of two input bits has degree 2. Low degree is a weakness: it makes a function vulnerable to higher-order-differential and cube techniques.

Chi is the single nonlinear step of Keccak-f. Along each 5-bit row it computes $y_i = x_i \oplus ((\lnot\, x_{i+1}) \land x_{i+2})$. Each output bit contains exactly one AND of two state bits, so chi has algebraic degree exactly 2. The other four steps of a round -- theta, rho, pi, iota -- are all linear or affine.
&lt;p&gt;Here is the load-bearing fact of the sponge&apos;s exposure, and it is worth deriving rather than asserting, because one word in it does real work.&lt;/p&gt;
&lt;p&gt;One round is the composition $R = \iota \circ \chi \circ \pi \circ \rho \circ \theta$. Four of those five steps are affine, degree 1; only chi is nonlinear, degree 2. Composing a degree-2 map with affine maps leaves the degree at 2, so a single round has $\deg(R) = 2$.&lt;/p&gt;
&lt;p&gt;Now use the composition bound for Boolean functions, $\deg(f \circ g) \le \deg(f) \cdot \deg(g)$, across $r$ rounds: $\deg(R^2) \le 2 \cdot 2 = 4$, $\deg(R^3) \le 2 \cdot 4 = 8$, and in general each extra round multiplies the bound by at most 2. The degree &lt;em&gt;doubles&lt;/em&gt; per round:&lt;/p&gt;
&lt;p&gt;$$1 ;\to; 2 ;\to; 4 ;\to; 8 ;\to; \cdots ;\to; 2^r, \qquad \text{so} \qquad \deg(\text{Keccak-}f^{,r}) \le 2^r.$$&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The degree &lt;em&gt;doubles&lt;/em&gt; each round, giving $\deg \le 2^r$. It does not &lt;em&gt;square&lt;/em&gt; each round -- squaring would compound as $2, 4, 16, 256, \ldots \approx 2^{(2^r)}$, a doubly-exponential growth that would make the bound useless within a few rounds and contradict the $2^r$ figure itself. The composition law multiplies the degree by at most $\deg(R) = 2$ each round, which is doubling. Getting this verb right is the difference between a bound that explains the whole algebraic frontier and one that is internally inconsistent.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You can watch chi&apos;s degree-2 structure force a higher-order derivative to vanish directly. A degree-$d$ function summed (XORed) over any affine cube of dimension $d+1$ gives zero, so summing degree-2 chi over any 3-dimensional cube must vanish.&lt;/p&gt;
&lt;p&gt;{`
// chi on a 5-bit row: y[i] = x[i] XOR ((NOT x[i+1]) AND x[i+2]), indices mod 5.
function chi(x) {
  let y = 0;
  for (let i = 0; i &amp;lt; 5; i++) {
    const xi  = (x &amp;gt;&amp;gt; i) &amp;amp; 1;
    const xi1 = (x &amp;gt;&amp;gt; ((i + 1) % 5)) &amp;amp; 1;
    const xi2 = (x &amp;gt;&amp;gt; ((i + 2) % 5)) &amp;amp; 1;
    const bit = xi ^ ((xi1 ^ 1) &amp;amp; xi2);   // one AND term =&amp;gt; algebraic degree 2
    y |= (bit &amp;lt;&amp;lt; i);
  }
  return y;
}&lt;/p&gt;
&lt;p&gt;// A degree-d function has a vanishing (d+1)-th order derivative:
// summing it over ANY affine cube of dimension d+1 gives 0.
// chi has degree 2, so summing over ANY 3-dimensional cube must XOR to 0.
function sumOverCube(base, d1, d2, d3) {
  let acc = 0;
  for (let m = 0; m &amp;lt; 8; m++) {
    let x = base;
    if (m &amp;amp; 1) x ^= d1;
    if (m &amp;amp; 2) x ^= d2;
    if (m &amp;amp; 4) x ^= d3;
    acc ^= chi(x);
  }
  return acc;
}&lt;/p&gt;
&lt;p&gt;console.log(&quot;chi(0b10110)          =&quot;, chi(0b10110));
console.log(&quot;3-cube sum (should 0) =&quot;, sumOverCube(0b00000, 0b00001, 0b00010, 0b00100));
console.log(&quot;3-cube sum (should 0) =&quot;, sumOverCube(0b10101, 0b00011, 0b01100, 0b10000));
`}&lt;/p&gt;
&lt;p&gt;One honesty note keeps this from overclaiming.The bound $\deg \le 2^r$ is the &lt;em&gt;elementary&lt;/em&gt; degree-doubling law, and it is only informative at low round counts. Keccak-f acts on 1600 bits, where &lt;em&gt;any&lt;/em&gt; permutation has degree at most 1599; $2^r$ already exceeds 1599 at $r = 11$, so the elementary bound says nothing about the full 24 rounds. The full-round result in Section 8 -- a zero-sum partition of size $2^{1590}$ -- rests instead on the tighter degree bound of Boura, Canteaut, and De Canniere, which stays below the state size even at 24 rounds [@boura-canteaut-decanniere-2011]. The elementary law is what caps the cube attack at a handful of rounds; the refined bound is what lets the zero-sum reach all 24. Keep them separate and the whole SHA-3 frontier stays legible.&lt;/p&gt;
&lt;p&gt;Now the two constructions can be laid side by side.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;SHA-2 (SHA-256)&lt;/th&gt;
&lt;th&gt;SHA-3 (SHA3-256 / SHAKE256)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Construction&lt;/td&gt;
&lt;td&gt;Merkle-Damgard + Davies-Meyer&lt;/td&gt;
&lt;td&gt;Keccak sponge over Keccak-f[1600]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full-function rounds/steps&lt;/td&gt;
&lt;td&gt;64 steps&lt;/td&gt;
&lt;td&gt;24 rounds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Leading structural avenue&lt;/td&gt;
&lt;td&gt;differential collision search (single)&lt;/td&gt;
&lt;td&gt;algebraic frontier + internal-differential (two)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best structural collision reach&lt;/td&gt;
&lt;td&gt;39/64 SFS; $\approx$ 31/64 from-IV&lt;/td&gt;
&lt;td&gt;6/24 (SHAKE256); 5/24 (SHA3-384)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Length extension&lt;/td&gt;
&lt;td&gt;yes (structural; digest is the full state)&lt;/td&gt;
&lt;td&gt;no (capacity hidden)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Generic collision target&lt;/td&gt;
&lt;td&gt;$2^{128}$&lt;/td&gt;
&lt;td&gt;$2^{128}$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; SHA-2 keeps the differential attack surface and the length-extension debt. The sponge trades both away for an algebraic surface whose degree grows only as $2^r$. The two functions do not sit on one strength axis, a bigger lock on the same door -- they expose &lt;em&gt;different&lt;/em&gt; attack surfaces, so they would die &lt;em&gt;different&lt;/em&gt; deaths. Construction, not digest size, selects the failure mode.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So the two constructions hand an attacker two different problems: thread a carry-laden differential path through 64 steps, or break the low-degree algebra of 24 rounds. How far has anyone actually gotten on each?&lt;/p&gt;
&lt;h2&gt;6. The Best Published Attacks, With Margins&lt;/h2&gt;
&lt;p&gt;Here is the scoreboard. After thirty-five years of cryptanalysis, where exactly does the deepest published structural attack stop on each function, and how far is that from the full thing? This is the article&apos;s quantitative core, and it comes with a reading rule that matters more than any single number.&lt;/p&gt;
&lt;p&gt;The yardstick never changes. A structural break must beat the generic birthday cost of $2^{n/2}$ on the &lt;em&gt;full&lt;/em&gt; function. On full SHA-256 and full SHA3-256, no published attack does; the best-known collision attack on either full function is still the generic one at $2^{128}$ [@li-liu-wang-2024, @dinur-etal-2015]. Every record below is progress on the &lt;em&gt;method&lt;/em&gt;, measured against a full function that remains untouched.&lt;/p&gt;
&lt;h3&gt;The SHA-2 record board&lt;/h3&gt;
&lt;p&gt;Against SHA-2, one avenue has all the reach: automated differential characteristic search -- the mechanized descendant of Wang&apos;s hand construction, driven by SAT and SMT solvers and steered by mixed-integer linear programming. Reading its records needs one distinction.&lt;/p&gt;

Attack models differ in how much freedom the attacker has over the chaining value. A *from-IV* collision uses the real fixed initialization value and is a true hash collision. A *semi-free-start* (SFS) collision lets the attacker choose the single chaining value both messages share. A *free-start* (FS) collision lets the attacker also choose a difference in the chaining value. SFS and FS are weaker attacker goals -- progress markers on the compression function, not full-hash collisions.
&lt;p&gt;The current records, all &lt;em&gt;practical&lt;/em&gt; (a real colliding pair verified on a PC, not merely a sub-birthday estimate), come from Mendel, Nad, and Schlaffer in 2013 and from Li, Liu, and Wang in 2024 [@mendel-nad-schlaffer-2013, @li-liu-wang-2024]:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Best reach&lt;/th&gt;
&lt;th&gt;Practical?&lt;/th&gt;
&lt;th&gt;Untouched margin&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;SHA-256&lt;/td&gt;
&lt;td&gt;from-IV&lt;/td&gt;
&lt;td&gt;31 / 64 steps&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;33 steps&lt;/td&gt;
&lt;td&gt;Mendel-Nad-Schlaffer 2013 [@mendel-nad-schlaffer-2013]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SHA-256&lt;/td&gt;
&lt;td&gt;semi-free-start&lt;/td&gt;
&lt;td&gt;39 / 64 steps&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;25 steps&lt;/td&gt;
&lt;td&gt;Li-Liu-Wang 2024 [@li-liu-wang-2024]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SHA-224&lt;/td&gt;
&lt;td&gt;free-start&lt;/td&gt;
&lt;td&gt;40 / 64 steps&lt;/td&gt;
&lt;td&gt;yes (prior best $2^{110}$)&lt;/td&gt;
&lt;td&gt;24 steps&lt;/td&gt;
&lt;td&gt;Li-Liu-Wang 2024 [@li-liu-wang-2024]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SHA-512&lt;/td&gt;
&lt;td&gt;semi-free-start&lt;/td&gt;
&lt;td&gt;28 practical / 31 theoretic of 80&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;49+ steps&lt;/td&gt;
&lt;td&gt;Li-Liu-Wang 2024 [@li-liu-wang-2024]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SHA3-384&lt;/td&gt;
&lt;td&gt;collision&lt;/td&gt;
&lt;td&gt;5 / 24 rounds&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;19 rounds&lt;/td&gt;
&lt;td&gt;Zhang-Hou-Liu 2024 [@zhang-hou-liu-2024]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SHAKE256&lt;/td&gt;
&lt;td&gt;collision&lt;/td&gt;
&lt;td&gt;6 / 24 rounds&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;18 rounds&lt;/td&gt;
&lt;td&gt;Zhang-Hou-Liu 2024 [@zhang-hou-liu-2024]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keccak (keyed)&lt;/td&gt;
&lt;td&gt;key recovery&lt;/td&gt;
&lt;td&gt;9 / 24 rounds&lt;/td&gt;
&lt;td&gt;6-round practical&lt;/td&gt;
&lt;td&gt;large&lt;/td&gt;
&lt;td&gt;Dinur et al. 2015 [@dinur-etal-2015]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keccak-f&lt;/td&gt;
&lt;td&gt;zero-sum distinguisher&lt;/td&gt;
&lt;td&gt;24 / 24 rounds&lt;/td&gt;
&lt;td&gt;structural set&lt;/td&gt;
&lt;td&gt;none, but no break&lt;/td&gt;
&lt;td&gt;Boura-Canteaut-De Canniere 2011 [@boura-canteaut-decanniere-2011]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The 2024 paper set three firsts at once: the first practical semi-free-start collision for 39-step SHA-256 (improving the decade-old 38-step SFS record), the first practical free-start collision for 40-step SHA-224 where the prior best was a theoretic attack at time complexity $2^{110}$, and practical and theoretic collisions for reduced SHA-512 [@li-liu-wang-2024]. Impressive -- and then the same authors say where the road ends.&lt;/p&gt;

&quot;The current advanced tool to search for SHA-2 characteristics has reached the bottleneck.&quot; -- Li, Liu, and Wang, on why the attack cannot climb past about 39 of 64 steps [@li-liu-wang-2024]
&lt;p&gt;The modular-addition diffusion from Section 5 is exactly what makes longer characteristics effectively unfindable with today&apos;s encodings.The three record numbers for the same function are not a contradiction -- they are three different attacker games. From-IV is a true collision on the real hash. Semi-free-start hands the attacker the shared chaining value. Free-start additionally hands them a chosen difference in it. Each added freedom buys a few more steps of reach, which is why SHA-256 shows 31 (from-IV), 39 (SFS), and its sibling SHA-224 shows 40 (FS). The from-IV number is the one that measures the real hash.&lt;/p&gt;
&lt;h3&gt;The SHA-3 record board&lt;/h3&gt;
&lt;p&gt;The sponge side has three attacks rather than one, and the next section is devoted to why they disagree about what &quot;progress&quot; means.&lt;/p&gt;
&lt;p&gt;For the scoreboard, the reduced-round facts are these. Cube and cube-like algebraic attacks reach up to 9 of the 24 rounds in &lt;em&gt;keyed&lt;/em&gt; Keccak modes, with the 6-round attacks fully practical on a desktop [@dinur-etal-2015]. Internal-differential collision cryptanalysis holds the actual &lt;em&gt;collision&lt;/em&gt; records: 5 of 24 rounds for SHA3-384 and 6 of 24 for SHAKE256 [@zhang-hou-liu-2024]. And a zero-sum distinguisher reaches all 24 rounds of the permutation while producing no collision at all [@boura-canteaut-decanniere-2011] -- the row we unpack next.&lt;/p&gt;
&lt;p&gt;The team that set the deepest keyed reach stated the bottom line directly.&lt;/p&gt;

&quot;The security margin of Keccak remains large.&quot; -- Dinur, Morawiecki, Pieprzyk, Srebrny, and Straus, whose cube-attack-like cryptanalysis reached the deepest keyed rounds [@dinur-etal-2015]
&lt;p&gt;Now state the margins plainly, because they are the number a practitioner actually needs. For SHA-256, the deepest collision result leaves roughly 25 of 64 steps untouched in the semi-free-start model and about 33 untouched from the real IV. For a Keccak &lt;em&gt;collision&lt;/em&gt;, roughly 18 of 24 rounds remain untouched. Those are not narrow escapes; they are the bulk of each function.&lt;/p&gt;
&lt;p&gt;{`
// A toy keyed function of public bits p0,p1 and secret key bits k0,k1.
// Algebraic degree 2 -- the product (p0 AND p1) is the only quadratic term.
function f(p0, p1, k0, k1) {
  return ((p0 &amp;amp; p1) ^ (p1 &amp;amp; k0) ^ (p0 &amp;amp; k1) ^ k0) &amp;amp; 1;
}&lt;/p&gt;
&lt;p&gt;// Cube over the single public variable p0: XOR f over p0 in {0,1}.
// The resulting &quot;superpoly&quot; is LINEAR in the key -- it equals p1 XOR k1.
function cubeSumOverP0(p1, k0, k1) {
  return f(0, p1, k0, k1) ^ f(1, p1, k0, k1);
}&lt;/p&gt;
&lt;p&gt;// The attacker cannot see the key. Say the hidden key is:
const K0 = 1, K1 = 0;&lt;/p&gt;
&lt;p&gt;// Query with p1 = 0 and sum the cube: the quadratic term dies and k1 falls out.
const recovered = cubeSumOverP0(0, K0, K1);
console.log(&quot;cube superpoly at p1=0 recovers k1 =&quot;, recovered, &quot;(true k1 =&quot;, K1, &quot;)&quot;);&lt;/p&gt;
&lt;p&gt;// The same reading discipline for any reduced-round headline:
function margin(reached, total, unit) {
  return &quot;reached &quot; + reached + &quot;/&quot; + total + &quot; &quot; + unit +
         &quot;  -&amp;gt;  &quot; + (total - reached) + &quot; &quot; + unit + &quot; still untouched&quot;;
}
console.log(margin(39, 64, &quot;SHA-256 steps&quot;));
console.log(margin(6, 24, &quot;SHAKE256 rounds&quot;));
`}&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A headline of &quot;39 of 64 steps&quot; or &quot;6 of 24 rounds&quot; is not &quot;almost broken.&quot; A reduced-round record measures &lt;em&gt;distance to a break&lt;/em&gt;, not &lt;em&gt;nearness&lt;/em&gt; to one. The record climbs by one or two steps every few years, against a function whose full round count has never been threatened. Treat every such headline as a ruler laid against the margin, and the panic evaporates.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;One number on the SHA-3 side hides an argument, though. The deepest result of all -- the zero-sum -- reaches every one of Keccak&apos;s 24 rounds, and still breaks nothing. To see why, look at the three rival attacks on the sponge side by side.&lt;/p&gt;
&lt;h2&gt;7. The SHA-3 Fork the Thesis Holds Open&lt;/h2&gt;
&lt;p&gt;SHA-2&apos;s story has one protagonist: differential collision search, with no rival of comparable reach. SHA-3&apos;s story has three, and they disagree about what the word &quot;reach&quot; even means. Pretending that one of them is &lt;em&gt;the&lt;/em&gt; SHA-3 break would misrepresent the field, so this section keeps the fork open.&lt;/p&gt;
&lt;h3&gt;Method A: cube and cube-like attacks&lt;/h3&gt;
&lt;p&gt;The cube attack, introduced by Itai Dinur and Adi Shamir in 2009, is the avenue the title of this article names the &lt;em&gt;algebraic frontier&lt;/em&gt;, because it exploits the low degree that chi keeps small at low round counts [@dinur-shamir-2009].&lt;/p&gt;

An algebraic attack that treats each output bit as an unknown low-degree polynomial over GF(2) in the public and secret input bits. Summing the output over a *cube* -- all $2^{k}$ assignments of $k$ chosen public variables -- cancels every term that does not contain all $k$ cube variables, leaving a lower-degree &quot;superpoly.&quot; Choose the cube so the superpoly is linear in the secret bits, collect enough such equations, and solve for the key.
&lt;p&gt;The method is provably successful on random low-degree polynomials whenever the number of public variables exceeds $d + \log_d n$, and it runs in about $2^{d-1} n + n^2$ bit operations for degree $d$ over $n$ secret variables [@dinur-shamir-2009].&lt;/p&gt;
&lt;p&gt;Against Keccak, Dinur, Morawiecki, Pieprzyk, Srebrny, and Straus reached up to 9 of the 24 rounds faster than exhaustive search, with the 6-round attacks fully practical [@dinur-etal-2015]. But note precisely what it threatens: key recovery or forgery in &lt;em&gt;keyed&lt;/em&gt; Keccak modes -- not a plain hash collision.The cube round counts come from keyed Keccak variants such as message authentication codes and the Keyak authenticated-encryption scheme, whose nominal round count is 12. In those modes a secret key exists to recover. Standard SHA3-256 hashing has no key, so the cube attack does not by itself produce a hash collision -- it is the deepest &lt;em&gt;algebraic&lt;/em&gt; reach, in a different attack model. And because the degree doubles each round, the cube needed grows astronomically past a handful of rounds, which is exactly why it stalls at 9.&lt;/p&gt;
&lt;h3&gt;Method B: zero-sum distinguishers&lt;/h3&gt;
&lt;p&gt;Take the same low-degree property but drop the key, and you get a statement about the raw permutation. Christina Boura, Anne Canteaut, and Christophe De Canniere used a refined bound on the degree of iterated permutations to build zero-sum partitions of size $2^{1590}$ for the &lt;em&gt;full&lt;/em&gt; 24-round Keccak-f [@boura-canteaut-decanniere-2011].&lt;/p&gt;
&lt;p&gt;This is the deepest structural reach anyone has into Keccak -- it touches every round -- and it is also the least usable result in the subject. It distinguishes the permutation from an ideal one; it yields no collision, no preimage, nothing against the hash. Hold that paradox; the next section is built on it.&lt;/p&gt;
&lt;h3&gt;Method C: internal-differential collisions&lt;/h3&gt;
&lt;p&gt;The record-holders work differently again -- and they are the avenue that produces the property that actually matters for a hash.&lt;/p&gt;

Instead of a difference between two separate messages, an internal-differential attack exploits a difference *within a single state* -- for example, between translated copies of the state under Keccak&apos;s internal symmetry. Inputs that respect the symmetry are squeezed into a small subset of possible outputs, so a birthday search confined to that small subset finds collisions far below the usual $2^{n/2}$ cost.
&lt;p&gt;The line runs from Thomas Peyrin&apos;s generalized internal differentials in 2010, through Dinur, Dunkelman, and Shamir -- who produced actual collisions for 3-round Keccak, a 4-round Keccak-384 attack $2^{45}$ times faster than birthday, and collisions on 5 rounds of Keccak-256 [@dinur-dunkelman-shamir-2013] -- to Zhongyi Zhang, Chengan Hou, and Meicheng Liu, whose &quot;probabilistic linearization&quot; extended the records to 5 rounds of SHA3-384 and 6 of SHAKE256 [@zhang-hou-liu-2024]. This is the only avenue that delivers real collisions on the standardized instances.&lt;/p&gt;
&lt;p&gt;Now put the three side by side. The decisive column is not &quot;how many rounds&quot; but &quot;what property.&quot;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Cube / cube-like&lt;/th&gt;
&lt;th&gt;Zero-sum higher-order diff.&lt;/th&gt;
&lt;th&gt;Internal-differential collisions&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Property threatened&lt;/td&gt;
&lt;td&gt;keyed-mode key recovery / forgery&lt;/td&gt;
&lt;td&gt;permutation distinguisher (not a break)&lt;/td&gt;
&lt;td&gt;actual hash collisions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best round reach&lt;/td&gt;
&lt;td&gt;9 / 24 (keyed)&lt;/td&gt;
&lt;td&gt;24 / 24 (full permutation)&lt;/td&gt;
&lt;td&gt;6 / 24 (SHAKE256), 5 / 24 (SHA3-384)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Practical demo&lt;/td&gt;
&lt;td&gt;yes, 6-round&lt;/td&gt;
&lt;td&gt;structural ($2^{1590}$ sets)&lt;/td&gt;
&lt;td&gt;yes, actual collisions to 3-5 rounds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model&lt;/td&gt;
&lt;td&gt;keyed (MAC / AE)&lt;/td&gt;
&lt;td&gt;keyless permutation&lt;/td&gt;
&lt;td&gt;keyless hash / XOF&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What limits it&lt;/td&gt;
&lt;td&gt;degree doubles per round ($\deg \le 2^r$)&lt;/td&gt;
&lt;td&gt;capacity hides the permutation output&lt;/td&gt;
&lt;td&gt;characteristic decays with rounds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Structural motivation&lt;/td&gt;
&lt;td&gt;direct: low-degree chi&lt;/td&gt;
&lt;td&gt;direct: the degree bound&lt;/td&gt;
&lt;td&gt;indirect: Keccak internal symmetry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Source&lt;/td&gt;
&lt;td&gt;[@dinur-shamir-2009, @dinur-etal-2015]&lt;/td&gt;
&lt;td&gt;[@boura-canteaut-decanniere-2011]&lt;/td&gt;
&lt;td&gt;[@dinur-dunkelman-shamir-2013, @zhang-hou-liu-2024]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This is the honest balance the whole SHA-3 story turns on. The zero-sum method reaches all 24 rounds but yields no break; the cube method reaches 9 rounds but only in keyed modes; the internal-differential method reaches just 6 rounds but is the sole avenue that produces real collisions. The algebraic / cube line is the &lt;em&gt;distinctive, structurally-motivated&lt;/em&gt; frontier -- it follows directly from the degree-2 chi -- and the internal-differential line &lt;em&gt;holds the collision records&lt;/em&gt;. Both are leading; neither out-reaches the other on the property that matters to it. Contrast SHA-2, where differential collision search is the single leading avenue with no competitor of comparable reach.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Third-party cryptanalysis of all three families is tracked publicly by the designers [@keccak-third-party]. That middle row -- 24 rounds reached, nothing broken -- is not an accident of today&apos;s tooling. It is a &lt;em&gt;provable&lt;/em&gt; wall, and understanding why forces us to the theoretical limits.&lt;/p&gt;
&lt;h2&gt;8. The Ideal, the Bounds, and the Distinguisher Trap&lt;/h2&gt;
&lt;p&gt;Begin with the middle row from the last table, because it is the strangest fact in the subject. A zero-sum partition of size $2^{1590}$ reaches &lt;em&gt;all 24 rounds&lt;/em&gt; of Keccak-f -- the deepest structural property anyone has ever proved about it -- and it yields no collision, no preimage, nothing usable against the hash [@boura-canteaut-decanniere-2011]. How can the deepest result reach the whole function and still break nothing?&lt;/p&gt;
&lt;p&gt;First, the wall that neither function&apos;s attackers have crossed. On the &lt;em&gt;full&lt;/em&gt; SHA-256 and full SHA3-256, no published structural attack beats $2^{128}$ for a collision or $2^{256}$ for a preimage. Best-known equals generic on both, so the &quot;beat the birthday bound&quot; gap is not merely large -- it is &lt;em&gt;open and uncrossed&lt;/em&gt;. Nobody has closed &lt;em&gt;any&lt;/em&gt; of it on either full function [@fips-180-4, @fips-202]. Everything in Section 6 is reduced-round evidence about how far away the break is.&lt;/p&gt;
&lt;p&gt;Now the answer to the zero-sum paradox, which is a proof, not a hope.&lt;/p&gt;

A structured set of inputs whose images under the permutation XOR to zero and whose preimages also XOR to zero. Because Keccak-f has bounded algebraic degree forward and a low-degree inverse backward, one can build such a set straight through the permutation. It distinguishes Keccak-f from an ideal random permutation, and does nothing else.

A construction built on an ideal primitive is *indifferentiable* from a random oracle if no efficient distinguisher can tell them apart, even when the distinguisher is allowed to query the underlying primitive directly. It is the strong security notion for hash constructions: it certifies that the construction adds no exploitable structure of its own on top of the primitive.
&lt;p&gt;Bertoni, Daemen, Peeters, and Van Assche proved in 2008 that a sponge calling a random permutation is indifferentiable from a random oracle: the success probability of &lt;em&gt;any&lt;/em&gt; generic attack is at most its success probability against a true random oracle plus $N^2/2^{c-1}$, where $N$ is the number of queries to the permutation and $c$ is the capacity [@sponge-indiff, @keccak-sponge-duplex].&lt;/p&gt;
&lt;p&gt;The strength of the claim is the clause &quot;even when the distinguisher can query the permutation directly&quot; -- a simulator can answer those permutation queries consistently with random-oracle outputs up to about $2^{c/2}$ work. Below $2^{c/2}$ in the hidden capacity, nothing separates the sponge from an ideal object.&lt;/p&gt;
&lt;p&gt;That is what disarms the zero-sum. A zero-sum partition is a structural distinguisher of the &lt;em&gt;permutation&lt;/em&gt; f alone -- a global property of how f maps XOR structure. The indifferentiability theorem runs in exactly one direction: any attack on the sponge F implies a distinguisher on f, but &lt;em&gt;not the converse&lt;/em&gt;. Having a distinguisher on f does not hand you an attack on F. In the designers&apos; own words:&lt;/p&gt;

&quot;The existence of a structural distinguisher for f does not necessarily imply an attack or weakness in F.&quot; -- Bertoni, Daemen, Peeters, and Van Assche, on why a permutation property need not be a hash break [@keccak-sponge-duplex]
&lt;p&gt;Concretely, a collision requires &lt;em&gt;steering&lt;/em&gt; the rate bits of two different messages so that their squeezed outputs coincide across the hidden capacity. The zero-sum gives an attacker no such steering: it certifies a global XOR property of the permutation, not a way to aim two chosen inputs at one output through the capacity. So it lies &lt;em&gt;outside&lt;/em&gt; the class of exploitable structure that indifferentiability rules out, and a distinguisher whose success probability is zero below $2^{c/2}$, in the designers&apos; phrase, &quot;forms no threat&quot; [@keccak-sponge-duplex].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; A permutation distinguisher is not a hash break. &quot;Reaches all 24 rounds&quot; and &quot;produces a collision&quot; are provably &lt;em&gt;different&lt;/em&gt; statements, separated by the capacity&apos;s $2^{c/2}$ indifferentiability margin -- not merely by the current state of tooling. Depth of reach into the permutation is not nearness to a break of the hash. The capacity stands between them by design, and the standing between is a theorem.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; When you read a headline that an attack &quot;reaches the full permutation&quot; or &quot;distinguishes all rounds,&quot; resist the reflex to read it as near-catastrophe. For a sponge, a full-permutation distinguisher and a hash collision are separated by a proof. The distinguisher can be the deepest result in the field and still be the least dangerous one.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Two more limits complete the picture, one on each construction. On the sponge side, the full-round zero-sum exists only because of the &lt;em&gt;refined&lt;/em&gt; degree bound, not the elementary one.Recall from Section 5 that the elementary law $\deg \le 2^r$ goes vacuous by round 11 against a 1600-bit state. The 24-round zero-sum instead rests on Boura, Canteaut, and De Canniere&apos;s tighter bound for permutations whose nonlinear layer is parallel small S-boxes, which stays below the state size all the way to round 24 [@boura-canteaut-decanniere-2011]. The elementary law caps the cube attack; the refined law powers the distinguisher. On the Merkle-Damgard side, length extension is not a bug that a better implementation could remove -- it is a &lt;em&gt;provable inevitability&lt;/em&gt; of the untruncated construction. Because the SHA-2 digest is the whole final chaining value, anyone with $H(m)$ and $|m|$ can resume the iteration, full stop [@hac-chap9]. The only cures are to stop emitting the whole state (the sponge), hide enough of it (sufficient truncation), or wrap the hash (&lt;a href=&quot;https://paragmali.com/blog/the-tag-verified-the-cipher-held-the-forgery-went-through-a-/&quot; rel=&quot;noopener&quot;&gt;HMAC&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;So the limits cut both ways. The sponge is closer to the &lt;em&gt;ideal object&lt;/em&gt; -- indifferentiable up to the capacity, no length extension -- while SHA-2 is closer to the &lt;em&gt;ideal margin in practice&lt;/em&gt;, with the bulk of its steps untouched by any differential path. Neither is anywhere near falling. One scope marker remains, because readers always ask about it.&lt;/p&gt;

Quantum computing changes the constants, not the constructions. Grover&apos;s algorithm lowers a *preimage* search from $2^n$ to $2^{n/2}$, but it does *not* beat the classical $2^{n/2}$ birthday bound for *collisions* in realistic bounded-memory models, and it exploits no internal structure of either hash -- it is a generic square-root speedup that would apply equally to an ideal random oracle. So it is generic, not structural, and the correct hedge is simply *more output bits* (SHA-384, SHA-512, SHAKE256 at a longer output), not a new design [@nist-hash-policy]. Shor&apos;s algorithm, which does break things structurally, is irrelevant here: it factors integers and computes discrete logarithms, threatening asymmetric primitives such as RSA and elliptic-curve signatures, not symmetric hashes. In this series, Shor counts as structural math for those primitives; for SHA-2 and SHA-3 it simply does not apply.
&lt;p&gt;The limits leave exactly one question standing: if neither function is close to falling, where &lt;em&gt;would&lt;/em&gt; the next round of progress even come from?&lt;/p&gt;
&lt;h2&gt;9. Where the Next Round Would Come From&lt;/h2&gt;
&lt;p&gt;If either function is ever broken, the break will arrive through one of a small, nameable set of open problems. Naming them turns you from spectator into forecaster.&lt;/p&gt;

flowchart TD
    Q[&quot;Where would a break come from?&quot;] --&amp;gt; A[&quot;SHA-2: differential search&quot;]
    Q --&amp;gt; B[&quot;SHA-3: three avenues&quot;]
    A --&amp;gt; A1[&quot;OP-1: past ~40 of 64 steps? Stalled at 39&quot;]
    B --&amp;gt; B1[&quot;Cube: 9 of 24, keyed only&quot;]
    B --&amp;gt; B2[&quot;Internal-differential: 6 of 24 collisions&quot;]
    B --&amp;gt; B3[&quot;Zero-sum: 24 of 24, distinguisher only&quot;]
    B2 --&amp;gt; OP2[&quot;OP-2: close the ~18-round gap?&quot;]
    B3 --&amp;gt; OP4[&quot;OP-4: cross the capacity barrier?&quot;]
    A1 --&amp;gt; OP3[&quot;OP-3: beat 2^128 on a full function, THE break, none known&quot;]
    OP2 --&amp;gt; OP3
    OP4 --&amp;gt; OP3
&lt;p&gt;&lt;strong&gt;OP-1: Can differential characteristic search push SHA-256 past about 40 steps?&lt;/strong&gt; The full-function margin depends entirely on how far this single leading avenue can climb, and the 2024 record paper reports the tooling &quot;has reached the bottleneck&quot; -- modular-addition diffusion makes longer characteristics effectively unfindable with current encodings. Whether that is a fundamental barrier or an artifact of today&apos;s solvers is itself open [@li-liu-wang-2024].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;OP-2: Can any SHA-3 avenue close the roughly 18-round gap to a full-Keccak collision?&lt;/strong&gt; The best collision reach is 6 of 24 rounds, and the two leading avenues advance a round or two per decade, neither clearly out-reaching the other on its target property [@zhang-hou-liu-2024, @dinur-etal-2015].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;OP-3: Is there any structural attack that beats the birthday bound on either full family?&lt;/strong&gt; This is &lt;em&gt;the&lt;/em&gt; break -- and today the answer is a clean no. Best-known equals generic on both full functions; everything else in this article is reduced-round evidence about how far away this remains [@fips-180-4, @fips-202].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;OP-4: Why is the permutation-distinguisher / hash-collision divide so hard to cross?&lt;/strong&gt; The deepest reach into Keccak-f, the 24-round zero-sum, currently yields nothing usable against the hash. Section 8 argued the reason is structural: indifferentiability makes the capacity a genuine barrier, not merely a reduction nobody has found yet [@boura-canteaut-decanniere-2011, @sponge-indiff].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Only OP-3 is a break. OP-1, OP-2, and OP-4 are all measurements of &lt;em&gt;distance&lt;/em&gt; to OP-3. That reframing is the whole discipline of reading this field calmly: a reduced-round record moves a ruler, it does not open a door.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;None of this is the same as a proof of security. What cryptographers have &lt;em&gt;proved&lt;/em&gt; are &lt;em&gt;reductions&lt;/em&gt; -- collision resistance reduces to the compression function, sponge security reduces to the capacity -- plus the absence of any known attack that beats generic. &quot;No known structural attack&quot; is a strong empirical statement after thirty-five years of trying, but it is not &quot;proven unbreakable.&quot; Honesty about that gap is part of taking the subject seriously.&lt;/p&gt;
&lt;p&gt;None of these problems is close to solved -- which is exactly why the practical answer to &quot;what should I ship?&quot; is calm and specific.&lt;/p&gt;
&lt;h2&gt;10. What the Margins Mean on Monday Morning&lt;/h2&gt;
&lt;p&gt;So: should you change anything you shipped last week? Almost certainly not -- but there is exactly one structural gotcha worth ten minutes of your attention.&lt;/p&gt;
&lt;p&gt;Start with the reassurance. Both full functions are sound for their advertised properties. Every record in Section 6 is reduced-round; 39 of 64 steps of SHA-256 and 6 of 24 rounds of SHAKE256 do not threaten the full functions, which remain safe for collision, preimage, and second-preimage resistance [@li-liu-wang-2024, @zhang-hou-liu-2024]. Nothing in this article is a reason to rip out SHA-256.&lt;/p&gt;
&lt;p&gt;The one gotcha is &lt;a href=&quot;https://paragmali.com/blog/the-signature-was-valid-the-message-was-forged-a-field-guide/&quot; rel=&quot;noopener&quot;&gt;length extension&lt;/a&gt;, and it is a property of the construction, not a defect to be patched. If you ever compute a keyed digest as $H(\text{secret} ,|, \text{message})$ with a plain Merkle-Damgard hash and treat it as a MAC, an attacker who sees that digest can forge a valid one for a longer message without knowing the secret.&lt;/p&gt;

A construction that turns any iterated hash into a keyed message authentication code by nesting two hash calls, roughly $H((k \oplus opad) \,\|\, H((k \oplus ipad) \,\|\, m))$. The outer keyed hash means an attacker never sees a raw $H(\text{secret} \,\|\, \cdots)$ digest to extend, which is why HMAC defeats length extension even over SHA-256.
&lt;p&gt;The decision guide fits in one table.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Your need&lt;/th&gt;
&lt;th&gt;Use&lt;/th&gt;
&lt;th&gt;Why it works&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Keyed integrity / a MAC&lt;/td&gt;
&lt;td&gt;HMAC over SHA-2&lt;/td&gt;
&lt;td&gt;the outer keyed hash hides the extensible state [@rfc-2104]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A drop-in SHA-2 that resists extension&lt;/td&gt;
&lt;td&gt;SHA-512/256&lt;/td&gt;
&lt;td&gt;truncation hides 256 state bits, more than enough [@fips-180-4]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Length-extension immunity by construction&lt;/td&gt;
&lt;td&gt;SHA-3 or SHAKE&lt;/td&gt;
&lt;td&gt;the capacity is never emitted, so there is no state to resume [@fips-202]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What to avoid&lt;/td&gt;
&lt;td&gt;plain SHA-256(secret then message) as a MAC&lt;/td&gt;
&lt;td&gt;the digest is the full state, so it is forgeable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Need a keyed digest? Reach for HMAC or a SHA-3 / KMAC construction. Need a plain hash that will not leak its state? Use SHA-512/256 or any SHA-3 function. Do not hand-roll $H(\text{secret} ,|, m)$.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The mechanism is worth seeing once, because it explains why &quot;just hash the secret with the message&quot; fails.&lt;/p&gt;

sequenceDiagram
    participant D as Defender
    participant A as Attacker
    D-&amp;gt;&amp;gt;D: hash secret then message into digest t
    D-&amp;gt;&amp;gt;A: publish digest t and the message length
    Note over A: attacker never learns the secret
    A-&amp;gt;&amp;gt;A: resume internal state from t
    A-&amp;gt;&amp;gt;A: append glue padding then an evil suffix
    A-&amp;gt;&amp;gt;D: send forged message plus a new digest
    Note over D: the new digest verifies as a valid hash
&lt;p&gt;{`
// A toy Merkle-Damgard hash where the state IS the digest.
// This shows the STRUCTURE of length extension, not real SHA-256 output.
function compress(state, ch) {
  // stand-in mixing; a real f is Davies-Meyer over a block cipher
  return (((state &amp;lt;&amp;lt; 5) ^ (state &amp;gt;&amp;gt;&amp;gt; 2) ^ ch) &amp;gt;&amp;gt;&amp;gt; 0);
}
function hash(state, message) {
  for (let i = 0; i &amp;lt; message.length; i++) {
    state = compress(state, message.charCodeAt(i));
  }
  return state &amp;gt;&amp;gt;&amp;gt; 0;
}&lt;/p&gt;
&lt;p&gt;const IV = 0x9e3779b9;&lt;/p&gt;
&lt;p&gt;// Defender hashes a secret-prefixed message and publishes only the digest.
const secretPrefixed = &quot;SECRET-user=guest&quot;;
const digest = hash(IV, secretPrefixed);&lt;/p&gt;
&lt;p&gt;// Attacker never learns the secret, but the digest IS the state,
// so they resume from it and append a chosen suffix.
const suffix = &quot;&amp;amp;admin=true&quot;;
const forged = hash(digest, suffix);&lt;/p&gt;
&lt;p&gt;// In a real hash the attacker also splices in the glue padding,
// producing H(m || pad || suffix). Here (no padding) it lands exactly:
const legitimate = hash(IV, secretPrefixed + suffix);&lt;/p&gt;
&lt;p&gt;console.log(&quot;forged   =&quot;, forged);
console.log(&quot;expected =&quot;, legitimate);
console.log(&quot;match    =&quot;, forged === legitimate);
`}&lt;/p&gt;
&lt;p&gt;A worked forgery for SHA-256 and SHA-512 is exactly what the hash_extender tool automates [@hash-extender]. But truncation is where the naive intuition &quot;any truncation stops extension&quot; quietly fails, and SHA-224 is the trap.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; SHA-224 is SHA-256 truncated to 224 bits, so it emits seven of the eight 32-bit words of the internal state and hides only one -- about 32 bits. An attacker who wants to resume the iteration is missing just those $2^{32}$ possibilities, which is a brute-force search a laptop finishes quickly, after which extension proceeds normally. So SHA-224 is &lt;em&gt;not&lt;/em&gt; immune to length extension; it merely raises the bar by a weak 32-bit margin. That point is a &lt;em&gt;structural word-count&lt;/em&gt; argument, not something the standard tool shows: hash_extender declines to implement SHA-224 precisely because the naive extension does not directly apply, so it lists SHA-224 as &quot;not&quot; vulnerable [@hash-extender]. Do not read that &quot;not&quot; as safety -- read it as &quot;32 bits of margin.&quot; True immunity needs a truncation that hides &lt;em&gt;enough&lt;/em&gt; state, which is why SHA-512/256, hiding 256 bits, genuinely resists extension and SHA-224 does not [@fips-180-4].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Two smaller notes round out the practical picture. First, a naming hazard that bites developers.Ethereum&apos;s &quot;Keccak-256&quot; is not SHA3-256. Ethereum froze the original Keccak submission before FIPS 202 added its domain-separation padding, so the two functions append different bits before permuting and therefore produce &lt;em&gt;different digests on the same input&lt;/em&gt; [@fips-202]. Code that assumes they are interchangeable will compute the wrong hash. This is a padding difference, not a security difference -- but it is a real bug source. Second, the quantum question again: if you are hedging against a future quantum adversary, the move is a &lt;em&gt;longer digest&lt;/em&gt; -- SHA-384, SHA-512, or SHAKE256 at a longer output -- not a migration to a different construction, because Grover is a generic speedup that a bigger output absorbs [@nist-hash-policy].&lt;/p&gt;
&lt;p&gt;Every one of these recommendations is a corollary of a single idea -- the construction decides the failure mode. A few common misconceptions fall out of the same idea, and they are worth clearing up directly.&lt;/p&gt;
&lt;h2&gt;11. Misconceptions the Structural View Corrects&lt;/h2&gt;
&lt;p&gt;Six questions whose honest answers are all the same idea in disguise: the construction, not the digest size, decides the failure mode.&lt;/p&gt;


No -- it *supplements* the SHA-2 family rather than replacing it, and NIST sees no need to migrate; the two coexist as deliberate design diversity, so a break in one construction leaves the other standing. See Section 4 [@fips-202, @nist-hash-policy].


Only for preimages, and only generically: Grover square-roots a preimage search but gives no real edge on collisions in bounded-memory models, so the hedge is a longer digest, not a new construction. See Section 8 [@nist-hash-policy].


No -- only a truncation that hides *enough* state. SHA-512/256 hides 256 bits and resists it; SHA-224 hides only about 32, a weak margin rather than true immunity. See the SHA-224 truncation trap in Section 10 [@fips-180-4].


No. A reduced-round record measures distance to a break, not nearness to one: the deepest results reach only about 39 of SHA-256&apos;s 64 steps and 6 of Keccak&apos;s 24 rounds. See Section 6 [@li-liu-wang-2024, @zhang-hou-liu-2024].


No. Ethereum froze the pre-FIPS-202 Keccak padding, so Keccak-256 and SHA3-256 return different digests on the same input -- same permutation, different padding. See Section 10 [@fips-202].


No -- it is a provable structural property of any untruncated Merkle-Damgard hash, removed (not patched) by HMAC, sufficient truncation, or the sponge. See Sections 2 and 10 [@rfc-2104, @fips-202].

&lt;p&gt;Every answer traces back to the same sentence. It is worth stating that sentence one last time, with all the evidence now behind it.&lt;/p&gt;
&lt;h2&gt;12. The Construction Writes the Obituary&lt;/h2&gt;
&lt;p&gt;We opened with a claim that should have sounded like a bluff: that we could describe, mechanically, how each of these functions would fall before either has ever fallen. Now the description is complete, and the two obituaries share nothing but a date that has not arrived.&lt;/p&gt;
&lt;p&gt;SHA-2 would die the way MD5 and SHA-1 died -- a Wang-style differential collision threaded through its compression function, deterministic in the early steps and cheap through the tail. It survives today only because its carry-laden schedule keeps that path unfindable past about 39 of 64 steps, and it carries length extension as a structural debt from the 1989 bargain [@li-liu-wang-2024].&lt;/p&gt;
&lt;p&gt;SHA-3 would die a different death entirely, on the algebra of a single degree-2 step: the cube frontier that stalls at 9 keyed rounds, and the internal-differential collisions that hold the records at 6 [@zhang-hou-liu-2024]. Its deepest known property reaches all 24 rounds and still breaks nothing, because the capacity provably stands between a permutation distinguisher and a hash collision.&lt;/p&gt;
&lt;p&gt;And the margins are the payoff. Roughly 25 to 33 of SHA-256&apos;s 64 steps, and roughly 18 of Keccak&apos;s 24 rounds, remain entirely untouched after thirty-five years of the best cryptanalysis in the world [@li-liu-wang-2024, @zhang-hou-liu-2024, @dinur-etal-2015]. The construction writes the obituary; the cryptanalysis only fills in the date, and the date is nowhere close.&lt;/p&gt;

The construction writes the obituary. A hash does not die at its digest size -- it dies where its construction is thinnest, and no two constructions are thin in the same place.
&lt;p&gt;That is the through-line, and it hands off cleanly. How these functions have actually failed people in the field -- Flame&apos;s rogue certificate, the long death of SHA-1 in the browser -- is a different kind of story, told by the empirical sibling to this piece, &quot;How the Hash Functions Broke in Real Life.&quot;&lt;/p&gt;
&lt;p&gt;And it points forward: if a hash&apos;s construction predicts its structural death, the natural next question for this series is whether the same is true for the ciphers and signature schemes still to come -- whether, for every primitive, the shape of the thing already names the way it would break.&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;how-sha2-and-sha3-would-break&quot; keyTerms={[
  { term: &quot;Merkle-Damgard construction&quot;, definition: &quot;Iterating a compression function from a fixed IV over padded message blocks; the digest is the final chaining value.&quot; },
  { term: &quot;Length extension&quot;, definition: &quot;Computing H(m plus pad plus y) from H(m) and the length of m, without knowing m, because the digest is the full internal state.&quot; },
  { term: &quot;Differential characteristic&quot;, definition: &quot;A step-by-step trail of input-to-output differences that ends in zero difference, the backbone of a collision attack.&quot; },
  { term: &quot;Message modification&quot;, definition: &quot;Solving the early sufficient conditions of a characteristic deterministically by adjusting free message words, collapsing the search cost to the tail.&quot; },
  { term: &quot;Sponge construction&quot;, definition: &quot;Absorbing message blocks into the rate of a large permutation and squeezing the digest from the rate, keeping the capacity hidden.&quot; },
  { term: &quot;Algebraic degree&quot;, definition: &quot;The size of the largest monomial in a function&apos;s algebraic normal form; Keccak&apos;s chi has degree 2.&quot; },
  { term: &quot;Zero-sum distinguisher&quot;, definition: &quot;A structured input set whose images and preimages both XOR to zero, a property of the permutation that is not a hash break.&quot; },
  { term: &quot;Indifferentiability&quot;, definition: &quot;A proof that a construction adds no exploitable structure over its primitive, up to about 2^(c/2) in the capacity for the sponge.&quot; }
]} questions={[
  { q: &quot;Why does a Merkle-Damgard hash die at a differential path rather than at its digest size?&quot;, a: &quot;Because a collision of the hash reduces to a collision of the compression function, and a differential characteristic plus message modification finds one far below the birthday bound.&quot; },
  { q: &quot;Why is SHA-2 more resistant to message modification than MD5 or SHA-1?&quot;, a: &quot;Its message schedule couples words through modular-addition carries, so solving one sufficient condition perturbs others, destroying the one-free-word-per-step structure.&quot; },
  { q: &quot;Why does the degree bound double per round instead of squaring?&quot;, a: &quot;The composition law multiplies the degree by at most deg(R) equals 2 each round, giving 1,2,4,8 up to 2^r; squaring would grow doubly-exponentially and contradict the 2^r bound.&quot; },
  { q: &quot;Why is a full-round zero-sum distinguisher not a collision?&quot;, a: &quot;The sponge is indifferentiable from a random oracle up to the capacity, so an attack on the sponge implies a distinguisher on the permutation but not the converse.&quot; },
  { q: &quot;What is the one practical gotcha the structural view flags?&quot;, a: &quot;Length extension: use HMAC, SHA-512/256, or SHA-3 rather than a plain keyed Merkle-Damgard digest, and note that SHA-224 hides only about 32 bits.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>sha-2</category><category>sha-3</category><category>keccak</category><category>cryptanalysis</category><category>hash-functions</category><category>merkle-damgard</category><category>length-extension</category><category>sponge-construction</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>How the Hash Functions Broke in Real Life: MD5, Flame, SHATTERED, and the Long Death of SHA-1</title><link>https://paragmali.com/blog/how-the-hash-functions-broke-in-real-life-md5-flame-shattere/</link><guid isPermaLink="true">https://paragmali.com/blog/how-the-hash-functions-broke-in-real-life-md5-flame-shattere/</guid><description>MD5 and SHA-1 were genuinely, mathematically broken -- yet every real breach still needed a second failure: a deployment still trusting the dead hash.</description><pubDate>Fri, 17 Jul 2026 00:00:00 GMT</pubDate><content:encoded>
**MD5 and SHA-1 -- the two hashes that once fingerprinted the entire internet -- are genuinely, mathematically broken.** Their collision resistance fell to cryptanalysis between 2004 and 2020. But every real breach they enabled -- the 2008 rogue certificate authority, 2012&apos;s Flame espionage malware, 2017&apos;s SHATTERED, 2020&apos;s Shambles -- needed a *second* failure beside the broken math: a deployment that had not yet stopped trusting the dead algorithm. That empirical record is the base rate that justifies migrating to SHA-2 and SHA-3, and it is why &quot;broken&quot; is narrower than you think: HMAC-SHA-1 is still fine, and preimage resistance held. Here is exactly what fell, what did not, and how to audit and migrate your own systems.
&lt;h2&gt;1. The Forged Certificate That Rode Windows Update&lt;/h2&gt;
&lt;p&gt;In the spring of 2012, espionage malware called Flame spread through the Middle East wearing a disguise almost nothing could see through: it arrived &lt;strong&gt;signed by Microsoft&lt;/strong&gt;, and reached some targets through &lt;strong&gt;Windows Update&lt;/strong&gt; itself [@kaspersky-flame-gadget]. 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 &lt;em&gt;chosen-prefix collision&lt;/em&gt; in &lt;strong&gt;MD5&lt;/strong&gt; -- a hash academics had called broken since 2004 [@wang2004-md5-eprint] -- and counterfeited a certificate that chained up to Microsoft&apos;s own root of trust [@stevens-counter-crypto-c13].&lt;/p&gt;
&lt;p&gt;The certificate they forged was not a plainly-issued code-signing certificate. It was a &lt;strong&gt;Terminal Server Licensing Service&lt;/strong&gt; certificate living inside Microsoft&apos;s &lt;strong&gt;Enforced Licensing&lt;/strong&gt; public-key infrastructure -- an obscure corner of Microsoft&apos;s PKI that the company was, in 2012, &lt;em&gt;still signing with MD5&lt;/em&gt;. When Microsoft published Security Advisory 2718704 on 3 June 2012, the fix was to revoke exactly those certificates: the &quot;Microsoft Enforced Licensing Intermediate PCA&quot; and the &quot;Microsoft Enforced Licensing Registration Authority CA&quot; [@ms-advisory-2718704].&lt;/p&gt;

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.
&lt;p&gt;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&apos;s paper read at a 2004 conference, and Microsoft&apos;s licensing servers were &lt;strong&gt;still signing with it&lt;/strong&gt; 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.&lt;/p&gt;
&lt;p&gt;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:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;38762cf7f55934b34d179ae6a4c80cadccbb7f0a&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;In February 2017, researchers at CWI Amsterdam and Google published two different PDF files that both hash to exactly that value [@shattered-2017]. 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.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Every break in this story needed two failures at once: a hash whose collision resistance had already fallen, and a deployment that had not yet stopped trusting it. Cryptanalysis was necessary. It was never, by itself, sufficient.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That diagnostic sentence is the spine of everything that follows. It is also why this article is the honest exception in &lt;a href=&quot;https://paragmali.com/blog/how-aes-breaks-in-real-life-the-attacks-that-never-touched-t/&quot; rel=&quot;noopener&quot;&gt;a series otherwise arguing that the deployment breaks, not the math&lt;/a&gt;. 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.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;h2&gt;2. What a Hash Promises, and Which Clause Is Fragile&lt;/h2&gt;
&lt;p&gt;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.&lt;/p&gt;

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

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.

It is infeasible to find *any* two messages `m1` and `m2`, both of the attacker&apos;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.
&lt;p&gt;The gap between those last two properties is not cosmetic; it is exponential, and it has a name.&lt;/p&gt;

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.
&lt;p&gt;That square-root haircut is brutal. By that bound, a 128-bit MD5 digest [@rfc1321-md5] offers only about $2^{64}$ collision security, and a 160-bit SHA-1 digest only about $2^{80}$. Preimage and second-preimage attacks still cost close to the full $2^{128}$ or $2^{160}$, which is why -- spoiler for Section 8 -- those properties survived while collision resistance did not. When you hear &quot;MD5 is broken,&quot; the precise statement is &quot;MD5&apos;s roughly $2^{64}$ collision barrier fell far below $2^{64}$.&quot; It is not &quot;you can invert an MD5 hash.&quot;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Informal promise&lt;/th&gt;
&lt;th&gt;Generic attack cost&lt;/th&gt;
&lt;th&gt;What it protects&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Preimage resistance&lt;/td&gt;
&lt;td&gt;Cannot find any message for a given digest&lt;/td&gt;
&lt;td&gt;about &lt;code&gt;2^n&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Password storage, commitments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Second-preimage resistance&lt;/td&gt;
&lt;td&gt;Cannot match a &lt;em&gt;given&lt;/em&gt; message&apos;s digest with another&lt;/td&gt;
&lt;td&gt;about &lt;code&gt;2^n&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Integrity of one known file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Collision resistance&lt;/td&gt;
&lt;td&gt;Cannot find &lt;em&gt;any&lt;/em&gt; two messages sharing a digest&lt;/td&gt;
&lt;td&gt;about &lt;code&gt;2^(n/2)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Certificates, signatures, content addressing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;One construction under all of them&lt;/h3&gt;
&lt;p&gt;MD5, SHA-1, and SHA-2 are not three unrelated designs. They are three members of one family, built from the same skeleton.&lt;/p&gt;

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.

flowchart LR
    IV[&quot;Fixed IV&quot;] --&amp;gt; F1[&quot;Compress&quot;]
    M1[&quot;Block 1&quot;] --&amp;gt; F1
    F1 --&amp;gt; F2[&quot;Compress&quot;]
    M2[&quot;Block 2&quot;] --&amp;gt; F2
    F2 --&amp;gt; F3[&quot;Compress&quot;]
    M3[&quot;Block 3 plus length padding&quot;] --&amp;gt; F3
    F3 --&amp;gt; D[&quot;Digest&quot;]
&lt;p&gt;Ronald Rivest published MD5 in April 1992 as RFC 1321, producing a 128-bit digest [@rfc1321-md5].Rivest is the &quot;R&quot; in RSA. MD5 was his hardened successor to MD4, and RFC 1321 says it &quot;backs off&quot; from MD4&apos;s speed for a &quot;greater likelihood of ultimate security.&quot; The US government&apos;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 [@fips-180-1].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.&lt;/p&gt;
&lt;h3&gt;Why a collision is a forgery&lt;/h3&gt;
&lt;p&gt;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 &lt;em&gt;the hash&lt;/em&gt; 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.&lt;/p&gt;

flowchart TD
    M1[&quot;Message A, benign&quot;] --&amp;gt; H[&quot;Hash function&quot;]
    M2[&quot;Message B, malicious&quot;] --&amp;gt; H
    H --&amp;gt; D[&quot;One shared digest&quot;]
    D --&amp;gt; S[&quot;Signer signs the digest&quot;]
    S --&amp;gt; Sig[&quot;A single signature&quot;]
    Sig --&amp;gt; Cover[&quot;Valid for A and for B&quot;]
&lt;p&gt;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 &lt;em&gt;only&lt;/em&gt; thing standing between &quot;sign this document&quot; and &quot;you just signed a document you never saw.&quot;&lt;/p&gt;
&lt;p&gt;{`&lt;/p&gt;
&lt;p&gt;  const safe = [&quot;hmac&quot;, &quot;checksum&quot;, &quot;legacy-verify&quot;, &quot;kdf&quot;];&lt;/p&gt;
&lt;p&gt;  if (collisionDependent.includes(use)) {
    return &quot;MIGRATE -- collision-dependent, move to SHA-2 or SHA-3&quot;;
  }
  if (safe.includes(use)) {
    return &quot;OK -- collision resistance is not relied on&quot;;
  }
  return &quot;REVIEW -- ask: can an adversary supply both inputs and profit?&quot;;
}&lt;/p&gt;
&lt;p&gt;[&quot;certificate&quot;, &quot;hmac&quot;, &quot;git-object&quot;, &quot;checksum&quot;, &quot;code-signing&quot;].forEach(function (u) {
  console.log(u, &quot;-&amp;gt;&quot;, auditHashUse(u));
});
`}&lt;/p&gt;
&lt;h3&gt;Choosing a target&lt;/h3&gt;
&lt;p&gt;Once you know a use must move, pick the destination by requirement, not by fashion. &lt;strong&gt;SHA-256&lt;/strong&gt; 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 [@fips-180-4-sha2, @nist-policy-hash]. Want length-extension resistance for free? &lt;strong&gt;SHA-512/256&lt;/strong&gt; truncates a wider computation and never leaks its full state [@fips-180-4-sha2]. Want structural diversity or an extendable-output function? Reach for &lt;strong&gt;SHA-3 or SHAKE&lt;/strong&gt; [@fips-202-sha3].&lt;/p&gt;
&lt;p&gt;If raw speed dominates and a FIPS stamp is not required, &lt;strong&gt;BLAKE3&lt;/strong&gt; is the fastest of the group and length-extension-immune [@blake3-repo]. And if you are stuck on a SHA-1 you cannot rip out this quarter, deploy &lt;code&gt;sha1dc&lt;/code&gt; collision detection the way Git did, then schedule the real migration behind it [@sha1dc-stevens-shumow-2017].&lt;/p&gt;
&lt;h3&gt;The mistakes, mapped to the breaks&lt;/h3&gt;
&lt;p&gt;Every common hashing mistake is a small echo of one of the four incidents. Naming the echo makes the fix obvious.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;The mistake&lt;/th&gt;
&lt;th&gt;The break it echoes&lt;/th&gt;
&lt;th&gt;The fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;MD5 or SHA-1 for certificates or code signing&lt;/td&gt;
&lt;td&gt;Rogue CA (2008), Flame (2012)&lt;/td&gt;
&lt;td&gt;SHA-256 signatures [@fips-180-4-sha2]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SHA-1 as a content-address or dedup key&lt;/td&gt;
&lt;td&gt;SHATTERED (2017)&lt;/td&gt;
&lt;td&gt;SHA-256 objects, &lt;code&gt;sha1dc&lt;/code&gt; as a stopgap [@sha1dc-stevens-shumow-2017]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SHA-1 for identity or Web-of-Trust signatures&lt;/td&gt;
&lt;td&gt;Shambles (2020), CVE-2019-14855&lt;/td&gt;
&lt;td&gt;Modern GnuPG on SHA-256 [@shambles-2020]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;H(secret || message)&lt;/code&gt; used as a MAC&lt;/td&gt;
&lt;td&gt;Length extension&lt;/td&gt;
&lt;td&gt;HMAC, or KMAC on SHA-3 [@rfc2104-hmac]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Assuming a collision break means a preimage break&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Keep salted preimage and HMAC uses; migrate only collision-dependent ones [@nist-policy-hash]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Two pitfalls deserve their own warning because they masquerade as fixes. Swapping Ethereum&apos;s Keccak-256 for standardized SHA3-256 silently changes your digests [@fips-202-sha3]. And treating &lt;code&gt;sha1dc&lt;/code&gt; 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.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Whatever legacy you must tolerate, draw one hard line: never &lt;em&gt;generate&lt;/em&gt; a new MD5 or SHA-1 signature, certificate, or code-signing object. Every incident in this article began where a system was still willing to sign with a dead hash.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;h2&gt;11. The Base Rate&lt;/h2&gt;
&lt;p&gt;Return to the digest from the opening: &lt;code&gt;38762cf7f55934b34d179ae6a4c80cadccbb7f0a&lt;/code&gt;. You can read it now. It is a SHA-1 value shared by two different PDFs -- an &lt;em&gt;identical-prefix&lt;/em&gt; 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 [@shattered-2017]. That one artifact contains the whole argument in miniature: a real mathematical break, precisely scoped, whose damage depended entirely on what still trusted it.&lt;/p&gt;
&lt;p&gt;Stretch that artifact across nearly four decades. From MD5&apos;s publication in 1992 to the federally mandated retirement of its successor SHA-1 in 2030 is a thirty-eight-year empirical record [@rfc1321-md5, @nist-sha1-retire-2022]. Inside it sit four undisputed, reproducible, weaponized breaks -- the 2008 rogue CA, 2012&apos;s Flame, 2017&apos;s SHATTERED, 2020&apos;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.&lt;/p&gt;

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.
&lt;p&gt;That is how this article honors the series&apos; 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&apos;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.&lt;/p&gt;
&lt;p&gt;And keep the boundary honest, because the slogan overreaches in both directions. &quot;Broken&quot; is scoped to collision-dependent uses: HMAC-SHA-1 survives on a proof, and preimage resistance held [@rfc2104-hmac, @nist-policy-hash]. 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&apos;s structural blind spot.&lt;/p&gt;
&lt;p&gt;For the mechanisms of how the successors themselves could someday be attacked -- Merkle-Damgard collisions, length extension, and the sponge&apos;s algebraic frontier -- see the structural sibling to this piece, &lt;a href=&quot;https://paragmali.com/blog/how-sha-2-and-sha-3-would-break-merkle-damgard-collisions-le/&quot; rel=&quot;noopener&quot;&gt;&lt;em&gt;How SHA-2 and SHA-3 Would Break&lt;/em&gt;&lt;/a&gt;, along with the series&apos; 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.&lt;/p&gt;
&lt;h2&gt;12. Frequently Asked Questions&lt;/h2&gt;


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 [@rfc2104-hmac, @nist-policy-hash]. &quot;Broken&quot; is a statement about one property, not the whole function.


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 [@shattered-2017]. Shambles (2020) is a chosen-prefix collision: strictly more powerful, and the capability that actually forges certificates and impersonates identities [@shambles-2020].


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 [@sha1dc-stevens-shumow-2017, @git-hash-transition]. The transition is staged and largely unfinished; do not assume your repository has migrated.


Yes. HMAC&apos;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 [@rfc2104-hmac]. You do not need to rip HMAC-SHA-1 out on account of SHATTERED or Shambles.


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 [@joux-multicollisions-c04]. Cascading broken hashes is a dead end; migrate to a single strong hash instead.


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 [@fips-202-sha3].


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 [@nist-policy-hash]. Never use either for a new signature, certificate, or code-signing operation.

&lt;p&gt;&amp;lt;StudyGuide slug=&quot;how-hash-functions-broke-in-real-life&quot; keyTerms={[
  { term: &quot;Collision resistance&quot;, definition: &quot;The infeasibility of finding any two messages that share a digest. The fragile promise that fell for MD5 and SHA-1.&quot; },
  { term: &quot;Birthday bound&quot;, definition: &quot;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.&quot; },
  { term: &quot;Identical-prefix collision&quot;, definition: &quot;Two near-twin messages that share a prefix and one digest. Breaks content addressing but cannot forge a chosen identity.&quot; },
  { term: &quot;Chosen-prefix collision&quot;, definition: &quot;Two different attacker-chosen prefixes driven to one digest. The hinge capability that turns a collision into a forgery.&quot; },
  { term: &quot;Merkle-Damgard construction&quot;, definition: &quot;The iterated compression design shared by MD5, SHA-1, and SHA-2, which also carries length extension as a structural liability.&quot; },
  { term: &quot;HMAC&quot;, definition: &quot;A keyed authenticator whose security rests on a pseudorandom-function assumption, not collision resistance, so HMAC-SHA-1 remains safe.&quot; }
]} questions={[
  { q: &quot;Why did a working MD5 collision in 2004 not immediately forge certificates?&quot;, a: &quot;It was an identical-prefix collision, which cannot encode two different chosen identities. Forgery needed the chosen-prefix capability from 2007.&quot; },
  { q: &quot;What were the two failures behind every breach in this article?&quot;, a: &quot;A hash whose collision resistance had already fallen, and a deployment that still trusted it, such as RapidSSL, Microsoft&apos;s licensing PKI, or GnuPG 1.4.&quot; },
  { q: &quot;Why do SHA-2 and SHA-3 both exist if neither is broken?&quot;, a: &quot;Diversification. SHA-3&apos;s sponge fails differently from Merkle-Damgard and is immune to length extension, so it is a structurally different backup.&quot; },
  { q: &quot;Is HMAC-SHA-1 affected by SHATTERED or Shambles?&quot;, a: &quot;No. HMAC does not rely on collision resistance, so those collision attacks do not compromise it.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>hash-functions</category><category>md5</category><category>sha-1</category><category>collision-attack</category><category>cryptography</category><category>sha-2</category><category>sha-3</category><category>pki</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>The Fingerprint Two Files Shared: A Field Guide to Cryptographic Hashes</title><link>https://paragmali.com/blog/the-fingerprint-two-files-shared-a-field-guide-to-cryptograp/</link><guid isPermaLink="true">https://paragmali.com/blog/the-fingerprint-two-files-shared-a-field-guide-to-cryptograp/</guid><description>A field guide to cryptographic hashes: the one promise behind SHA-2, SHA-3, and BLAKE3, why MD5 and SHA-1 died, and how to choose one that keeps its promise.</description><pubDate>Fri, 10 Jul 2026 16:04:13 GMT</pubDate><content:encoded>
A cryptographic hash makes one promise: a short fingerprint that stands in, unforgeably and unambiguously, for any input. MD5 and SHA-1 are dead for collision-dependent uses. Their broken collision resistance was weaponized into forged certificates (the 2008 rogue certificate authority [@rogue-ca], Flame in 2012 [@stevens-counter-cryptanalysis-crypto13]) and forged documents and keys (SHAttered in 2017 [@shattered], Shambles in 2020 [@shambles]). Yet HMAC-SHA-1 is not broken [@rfc-2104], and &quot;dead&quot; never meant &quot;extinct.&quot; SHA-2 survived by widening the same Merkle-Damgard margins, while SHA-3&apos;s sponge and the BLAKE3 tree diversified the toolbox rather than replacing the survivor [@fips-202, @blake3-repo]. Correct usage is clause-matching: pick the function and the mode (bare hash, HMAC, KMAC or cSHAKE, an extendable-output function, or a password KDF) that keeps the exact clause your protocol leans on. This guide gives you the promise, the constructions, every named break with its root cause, and a decision tree you can apply the same afternoon.
&lt;h2&gt;1. The Fingerprint Two Files Shared&lt;/h2&gt;
&lt;p&gt;In February 2017, researchers at Google and CWI Amsterdam published two PDF files that looked nothing alike, with different visible content and different bytes, yet when a computer fingerprinted each of them with SHA-1 it returned the very same 40-hex-digit answer: &lt;code&gt;38762cf7f55934b34d179ae6a4c80cadccbb7f0a&lt;/code&gt; [@shattered]. Two different files, one identical fingerprint. Five years earlier, malware named Flame had used the same species of trick against the older MD5 hash to forge a code-signing certificate that chained up to Microsoft and rode Windows Update onto target machines as if Microsoft itself had signed it [@stevens-counter-cryptanalysis-crypto13].&lt;/p&gt;
&lt;p&gt;Neither of those is a stunt. They are the failure mode of one of the quietest, most load-bearing primitives in computing. A cryptographic hash function takes an input of any size and returns a short, fixed-length string of bits, its digest or fingerprint, and it promises something enormous: that fingerprint stands in for the whole input unforgeably and unambiguously.&lt;/p&gt;
&lt;p&gt;Almost everything you trust online leans on that promise. A certificate authority does not sign your certificate; it signs a hash of it. Code signing signs a hash of the program. A TLS 1.3 handshake authenticates a hash of the transcript. Every Git commit names its parent by hash, and every blockchain block commits to its transactions through a tree of hashes. When the promise holds, all of that machinery works. When it breaks, it breaks silently and all at once.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; A cryptographic hash is infrastructure hiding in plain sight. Because signatures, certificates, and integrity checks all sign the digest rather than the data, a break in the hash silently breaks every signature built on top of it. The attacker never has to touch your private key.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is what makes the two colliding PDFs unsettling rather than merely clever. If an adversary can produce two inputs with the same fingerprint, then any signature over one of them is also a valid signature over the other, and the entire chain of trust resting on that hash quietly inverts. This guide answers four questions in order: what exactly is the promise a hash makes, how is the fingerprint built, how has it broken in the real world, and how do you choose one today that will not break under you.&lt;/p&gt;

flowchart TD
    A[&quot;One promise: a short, unforgeable, unambiguous fingerprint&quot;] --&amp;gt; B[&quot;How it is built: the Merkle-Damgard chain and the sponge&quot;]
    B --&amp;gt; C[&quot;How it broke: MD5 and SHA-1 collisions weaponized into forgery&quot;]
    C --&amp;gt; D[&quot;What survived: SHA-2 widened the same margins&quot;]
    D --&amp;gt; E[&quot;What diversified: the SHA-3 sponge, the BLAKE3 tree, KangarooTwelve&quot;]
    E --&amp;gt; F[&quot;How to choose: match the function and mode to the clause you rely on&quot;]
&lt;p&gt;A preview of the plot, because it corrects the single most common misconception in the whole subject. Some hashes died and were superseded: MD5 gave way to SHA-1, which gave way to SHA-2. But SHA-2 did not then give way to SHA-3. Instead the field forked. One arc is supersession by failure; the other is deliberate diversification, where several unbroken constructions coexist on purpose so the internet&apos;s trust machinery never again rests on a single design. Telling those two arcs apart is most of what it means to understand this topic.&lt;/p&gt;
&lt;p&gt;Before we can understand how the fingerprint was forged, we have to say, precisely, what it was ever supposed to guarantee.&lt;/p&gt;
&lt;h2&gt;2. What a Hash Actually Promises&lt;/h2&gt;
&lt;p&gt;Ask three engineers what a &quot;secure hash&quot; means and you will get three answers: it is one-way, it has no collisions, it looks random. Cryptographers are more disciplined. They name exactly three properties, plus one more that everyone wishes were true and no real function actually delivers. Getting these four straight is the whole vocabulary, because every break later in this guide is best described as one specific property falling while the others stand.&lt;/p&gt;
&lt;p&gt;Start with the object itself. A hash function $H$ maps an input of essentially unbounded length to an output of some fixed length $n$ bits: 256 bits for SHA-256, 160 for SHA-1, 128 for MD5. Because the input space is infinite and the output space has only $2^n$ points, collisions must exist by counting alone. Security is never about avoiding collisions in principle; it is about making them, and two related feats, computationally unreachable.&lt;/p&gt;
&lt;p&gt;Phillip Rogaway and Thomas Shrimpton gave the field its rigorous, separated definitions of these properties in 2004, and it is worth stating them the way they did, because the separations matter [@rogaway-shrimpton-fse04].&lt;/p&gt;

A deterministic function that maps an input of arbitrary length to a fixed-length digest, engineered so that the digest behaves like a compact, tamper-evident fingerprint of the input: cheap to compute forwards, and infeasible to invert, to steer to a chosen value, or to make two inputs share, except by effort that grows exponentially in the digest length.

Given only a target digest $y$, it is computationally infeasible to find any input $m$ with $H(m) = y$. This is the &quot;one-way&quot; property. For an ideal $n$-bit hash the generic cost is about $2^{n}$ evaluations, because you have no better strategy than trying inputs until one lands on $y$.

Given a specific input $m_1$, it is infeasible to find a different input $m_2 \ne m_1$ with $H(m_2) = H(m_1)$. The target is fixed and not of your choosing. The generic cost is again about $2^{n}$.

It is infeasible to find any two distinct inputs $m_1 \ne m_2$ with $H(m_1) = H(m_2)$. Here you are free to choose both inputs, which is exactly why it is easier to attack. The generic cost is only about $2^{n/2}$, by the birthday bound.
&lt;p&gt;The gap between $2^{n}$ and $2^{n/2}$ is the single most important number in this article. Preimage and second-preimage pit you against a fixed target, so you are searching a space of size $2^n$. Collision lets you range freely over pairs, and pairs accumulate quadratically.&lt;/p&gt;

In a space of $N = 2^{n}$ equally likely values, a randomly drawn set is more likely than not to contain a repeat after only about $\sqrt{N} = 2^{n/2}$ draws, because the number of candidate pairs among $k$ items grows like $k^2/2$. Formally the collision probability after $k$ draws is about $1 - e^{-k(k-1)/(2N)}$.
&lt;p&gt;The name comes from the party trick: in a room of just 23 people, two of them probably share a birthday, even though there are 365 candidate days, because 23 people form 253 pairs. For a 256-bit hash the same arithmetic says a collision surfaces after about $2^{128}$ digests rather than $2^{256}$, so a 256-bit hash buys you only 128 bits of collision resistance. This is why collision is the weakest joint, and, as the failure catalog will show, always the first to fall.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Clause&lt;/th&gt;
&lt;th&gt;What the attacker must find&lt;/th&gt;
&lt;th&gt;Generic cost&lt;/th&gt;
&lt;th&gt;Who leans on it&lt;/th&gt;
&lt;th&gt;First to fall?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Preimage resistance&lt;/td&gt;
&lt;td&gt;Any input hashing to a given digest&lt;/td&gt;
&lt;td&gt;$2^{n}$&lt;/td&gt;
&lt;td&gt;Password hiding, commitments, key derivation&lt;/td&gt;
&lt;td&gt;Last&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Second-preimage resistance&lt;/td&gt;
&lt;td&gt;A different input matching one fixed input&lt;/td&gt;
&lt;td&gt;$2^{n}$&lt;/td&gt;
&lt;td&gt;Integrity of a known, published file&lt;/td&gt;
&lt;td&gt;Middle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Collision resistance&lt;/td&gt;
&lt;td&gt;Any two distinct inputs that agree&lt;/td&gt;
&lt;td&gt;$2^{n/2}$&lt;/td&gt;
&lt;td&gt;Signatures, certificates, deduplication&lt;/td&gt;
&lt;td&gt;First&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Second-preimage feels like it should be as easy as collision, but it is not. A collision lets you shop for any lucky pair anywhere in the space. A second preimage nails one endpoint to a value someone else chose and dares you to hit it from the other side, which is a $2^n$ problem, not a $2^{n/2}$ one. Attackers who can only find collisions therefore need to control both documents, which is precisely the constraint the forged-certificate attacks had to engineer around.&lt;/p&gt;
&lt;p&gt;The following simulator makes the gap tangible. It uses a toy 24-bit hash so both effects fit in a browser tab: watch how few inputs it takes to stumble into a collision, and how hopeless it is to hit one fixed target by search.&lt;/p&gt;
&lt;p&gt;{`
// A toy 24-bit &quot;hash&quot;: mix the input, then keep the low 24 bits (N = 2^24).
const N = 1 &amp;lt;&amp;lt; 24;                 // 16,777,216 possible digests
function h(x) {
  let v = Math.imul(x ^ 0x9e3779b1, 2654435761) &amp;gt;&amp;gt;&amp;gt; 0;
  v ^= v &amp;gt;&amp;gt;&amp;gt; 15;                    // fold high bits down so the low bits mix
  v = Math.imul(v, 0x85ebca6b) &amp;gt;&amp;gt;&amp;gt; 0;
  v ^= v &amp;gt;&amp;gt;&amp;gt; 13;
  return v &amp;amp; (N - 1);
}&lt;/p&gt;
&lt;p&gt;// Collision search: hash 1, 2, 3, ... and stop at the first repeat.
const seen = new Map();
let collisionAt = null;
for (let i = 1; i &amp;lt; 300000 &amp;amp;&amp;amp; collisionAt === null; i++) {
  const d = h(i);
  if (seen.has(d)) collisionAt = i;
  else seen.set(d, i);
}
console.log(&quot;birthday bound, sqrt(N), is about&quot;, Math.round(Math.sqrt(N)));
console.log(&quot;first collision appeared after only&quot;, collisionAt, &quot;inputs&quot;);&lt;/p&gt;
&lt;p&gt;// Preimage search: how many tries to hit ONE fixed target digest?
const target = h(42), budget = 500000;
let tries = 0, hit = false;
for (let x = 5000000; x &amp;lt; 5000000 + budget; x++) {
  tries++;
  if (h(x) === target) { hit = true; break; }
}
console.log(&quot;preimage search used&quot;, tries, &quot;tries and&quot;, hit ? &quot;got lucky&quot; : &quot;found nothing&quot;);
console.log(&quot;average preimage cost would be about N/2 =&quot;, N / 2, &quot;tries&quot;);
`}&lt;/p&gt;
&lt;p&gt;Collisions surface after only a couple of thousand inputs, while the fixed-target search burns through half a million tries and, on average, would need eight million. That is the $2^{n/2}$ versus $2^{n}$ split in miniature.&lt;/p&gt;
&lt;p&gt;There is a fourth property people silently assume: that a good hash behaves like a random oracle, a magic box that returns a fresh uniformly random answer for every distinct input and is otherwise consistent. It is a wonderful modeling fiction, and much of applied cryptography is proved secure by pretending it is real.&lt;/p&gt;
&lt;p&gt;But no fixed, finite, publicly specified function can actually be a random oracle, and Canetti, Goldreich, and Halevi proved the gap is not merely cosmetic: there exist schemes secure with an ideal oracle yet insecure under every concrete instantiation [@cgh-jacm-2004]. We make that precise in Section 10. For now, hold the three real clauses in mind, plus the knowledge that the fourth is a heuristic.&lt;/p&gt;
&lt;p&gt;Two consequences follow immediately and set up everything after. First, you never sign a document; you sign its digest, so a signature is only as unforgeable as the hash is collision resistant. The formal security goals for signatures and message authentication codes are the subject of Part 1 of this series, &lt;a href=&quot;https://paragmali.com/blog/secure-against-whom-the-security-definitions-every-protocol-&quot; rel=&quot;noopener&quot;&gt;the security-definitions field guide&lt;/a&gt;; here we only need the consequence. Second, the weakest clause is collision resistance, sitting at $2^{n/2}$. To see how that clause snapped in practice, we first have to see how the fingerprint is assembled, because the assembly leaks in ways the three clauses alone do not reveal.&lt;/p&gt;
&lt;h2&gt;3. How the Fingerprint Was Built: The Merkle-Damgard Era&lt;/h2&gt;
&lt;p&gt;The hash function became load-bearing infrastructure almost by accident. When Whitfield Diffie and Martin Hellman introduced public-key cryptography in 1976, their signatures could only operate on short numbers, roughly the size of the key [@diffie-hellman-1976]. But people wanted to sign whole documents, contracts, and programs. The fix was quiet and consequential: do not sign the document, sign a short fingerprint of it. That single move loaded the entire weight of a signature onto the hash. If two documents can share a fingerprint, one signature covers both, so the signature scheme is only as sound as the hash beneath it.&lt;/p&gt;
&lt;p&gt;Ralph Merkle&apos;s 1979 Stanford thesis formalized one-way hash functions and, in its &quot;Tree Authentication&quot; section, introduced the hash tree that now underlies Git, blockchains, and verified downloads [@merkle-thesis-1979].&lt;/p&gt;
&lt;p&gt;The next question was how to build such a fingerprint for an input of any length out of a small, analyzable building block. In 1989, Ralph Merkle and, independently, Ivan Damgard supplied the answer that defined the next two decades [@merkle-crypto89, @damgard-crypto89].&lt;/p&gt;

An iterated hash built by padding the message, splitting it into fixed-size blocks, and folding the blocks one at a time through a compression function, starting from a fixed initial value called the IV. Merkle and Damgard proved that if the compression function is collision resistant and the final block encodes the message length, a trick called MD strengthening, then the whole hash inherits collision resistance from the small compression function.
&lt;p&gt;That theorem is the reason the 1990s could build hashes with confidence: analyze one small function, get a hash for arbitrary inputs for free. The digest is simply the chaining state after the last block has been absorbed.&lt;/p&gt;

flowchart LR
    IV[&quot;IV: fixed start state&quot;] --&amp;gt; C1[&quot;compress&quot;]
    M1[&quot;block m1&quot;] --&amp;gt; C1
    C1 --&amp;gt; C2[&quot;compress&quot;]
    M2[&quot;block m2&quot;] --&amp;gt; C2
    C2 --&amp;gt; C3[&quot;compress&quot;]
    MP[&quot;final block: message plus length padding&quot;] --&amp;gt; C3
    C3 --&amp;gt; D[&quot;digest: the final chaining state&quot;]
&lt;p&gt;Ronald Rivest built the first widely used family on this shape. MD4 arrived in 1990 and the strengthened MD5 in 1992, both producing 128-bit digests from an add-rotate-xor compression function [@rivest-md4-crypto90, @rfc-1320]. RFC 1321 states MD5&apos;s purpose plainly: it compresses a message &quot;in a secure manner before being signed with a private key&quot; [@rfc-1321]. The design DNA, a message schedule feeding an ARX round function, propagated forward. In 1993 the U.S. government standardized a 160-bit hash of the same lineage in FIPS 180, retroactively called SHA-0, and in 1995 replaced it with SHA-1, a one-bit tweak of the same design [@nist-hash-functions]. SHA-1&apos;s specification survives in the current Secure Hash Standard [@fips-180-4], and it went on to hash most of the internet for roughly twenty years.&lt;/p&gt;
&lt;p&gt;The only visible difference between SHA-0 and SHA-1 is a single one-bit rotation added to the message schedule in 1995, a small and initially unexplained change later understood to improve collision resistance. The hedge held for a while, but SHA-0 was later shown to be genuinely fragile: Xiaoyun Wang and colleagues found efficient full collisions for SHA-0 well under the birthday bound in 2005 [@wang-yu-yin-sha0-crypto05]. The quietly patched flaw foreshadowed the cryptanalysis that would soon reach SHA-1 itself.&lt;/p&gt;

This detour, hashing before signing, is so routine that engineers forget it is a security assumption. A signature over `H(m)` is meant to bind you to `m`, but it truly binds you only to `H(m)`. If an adversary finds a second message with the same digest, your signature covers that message too, and no key was ever stolen. Every certificate, code signature, and signed software update in this article inherits this assumption, which is why a collision in the hash is not an academic curiosity but a forged signature waiting to happen.
&lt;p&gt;The Merkle-Damgard theorem promised something precise and limited: the whole hash is as collision resistant as its little compression function. It never promised that the shape wrapped around that function, the chaining, the padding, the exposed final state, was itself sound. That distinction is exactly where the first cracks opened, and they opened even for a hypothetically perfect compression function.&lt;/p&gt;
&lt;h2&gt;4. The Structural Cracks: Why Merkle-Damgard Leaks&lt;/h2&gt;
&lt;p&gt;Here is the unsettling part. You can hand the Merkle-Damgard construction a perfect compression function, one with no weakness whatsoever, and the assembled hash still leaks. It leaks four separate ways, and none of them is a bug in any particular function. They are properties of the shape.&lt;/p&gt;
&lt;p&gt;The first leak is the most practical, and it follows directly from the diagram in the previous section. The digest is the final chaining state. Nothing hides it. So if you know a digest and the length of the message that produced it, you can pick up the computation exactly where it left off.&lt;/p&gt;

Given a valid digest $H(m)$ and the length of $m$, but not $m$ itself, an attacker can compute $H(m \,\|\, \text{pad} \,\|\, s)$ for a suffix $s$ of their choosing. It works because a Merkle-Damgard digest is literally the internal chaining state after the last block, so the attacker resumes from that state and folds in more blocks, without ever knowing $m$.
&lt;p&gt;The mechanism has exactly three moving parts, and it needs neither the message nor any secret. Publishing $H(m)$ publishes a fully loaded, resumable hash engine. From the length of $m$ the attacker rebuilds the glue padding, the &lt;code&gt;0x80&lt;/code&gt; byte, the run of zeros, and the encoded bit-length that Merkle-Damgard appends before the final block [@fips-180-4]. The attacker reloads $H(m)$ as the IV, folds in the glue and then an arbitrary suffix, and reads off a valid digest for the longer message. When the server later hashes &lt;code&gt;secret || m || glue || suffix&lt;/code&gt; it walks the identical chain, passes through the intermediate state $H(m)$, folds in the same suffix, and confirms the forgery.&lt;/p&gt;

flowchart LR
    PUB[&quot;Public: digest H(m) and length of m&quot;] --&amp;gt; REBUILD[&quot;Rebuild glue padding from the length alone&quot;]
    REBUILD --&amp;gt; RELOAD[&quot;Reload H(m) as the compression IV&quot;]
    RELOAD --&amp;gt; FOLD[&quot;Fold in glue, then attacker suffix&quot;]
    FOLD --&amp;gt; FORGE[&quot;Forged digest for m plus glue plus suffix&quot;]
    SERVER[&quot;Server hashes secret plus m plus glue plus suffix&quot;] -.walks the identical chain.-&amp;gt; FORGE
&lt;p&gt;This turns a natural-looking construction into a trap. Many engineers reach for &lt;code&gt;H(secret || message)&lt;/code&gt; as a homemade message authentication code, reasoning that you cannot forge a tag without knowing the secret. Length extension refutes that: given a valid tag for one message, an attacker appends chosen data and computes a valid tag for the longer message, secret still unknown. The toy hash below is deliberately tiny and insecure, but it has the one property that matters, its digest is its whole internal state, so it forges end to end exactly as MD5 or SHA-256 would.&lt;/p&gt;
&lt;p&gt;{`
// A toy Merkle-Damgard hash. Like MD5 and SHA-256, its DIGEST IS ITS FINAL
// INTERNAL STATE -- that single fact is the entire length-extension bug.
const BLK = 8;
const IV = 0x1234abcd &amp;gt;&amp;gt;&amp;gt; 0;
const enc = s =&amp;gt; [...s].map(c =&amp;gt; c.charCodeAt(0));&lt;/p&gt;
&lt;p&gt;function compress(state, byte) {          // one toy ARX step (not secure)
  let s = (state + byte) &amp;gt;&amp;gt;&amp;gt; 0;
  s = ((s &amp;lt;&amp;lt; 7) | (s &amp;gt;&amp;gt;&amp;gt; 25)) &amp;gt;&amp;gt;&amp;gt; 0;
  return Math.imul(s ^ 0x9e3779b1, 2654435761) &amp;gt;&amp;gt;&amp;gt; 0;
}
function fold(state, bytes) {             // raw fold, adds no padding
  let s = state &amp;gt;&amp;gt;&amp;gt; 0;
  for (const b of bytes) s = compress(s, b);
  return s &amp;gt;&amp;gt;&amp;gt; 0;
}
function pad(len) {                       // MD strengthening from the LENGTH ALONE
  const p = [0x80];
  while ((len + p.length + 1) % BLK !== 0) p.push(0x00);
  p.push(len &amp;amp; 0xff);                     // 1-byte toy length encoding
  return p;
}
function toyHash(bytes) {                 // full hash = fold over message + padding
  return fold(IV, bytes.concat(pad(bytes.length)));
}&lt;/p&gt;
&lt;p&gt;// The server publishes (message, tag) where tag = H(secret || message).
const secret  = enc(&quot;SECRET&quot;);            // 6 bytes the attacker never sees
const message = enc(&quot;user=guest&quot;);
const tag = toyHash(secret.concat(message));&lt;/p&gt;
&lt;p&gt;// The attacker knows tag, message, and only the LENGTH of the secret (6).
const secretLen = 6;
const glue   = pad(secretLen + message.length);   // rebuilt from lengths, no secret
const suffix = enc(&quot;&amp;amp;role=admin&quot;);
const total  = secretLen + message.length + glue.length + suffix.length;
const forgedTag = fold(tag, suffix.concat(pad(total)));    // resume FROM the tag
const forgedMessage = message.concat(glue).concat(suffix);&lt;/p&gt;
&lt;p&gt;// The server verifies the forged message with its real secret.
const check = toyHash(secret.concat(forgedMessage));
console.log(&quot;forged tag (secret never used):&quot;, forgedTag.toString(16));
console.log(&quot;server recomputation          :&quot;, check.toString(16));
console.log(&quot;forgery accepted?&quot;, forgedTag === check);
console.log(&quot;smuggled &apos;role=admin&apos; present?&quot;, String.fromCharCode(...forgedMessage).includes(&quot;role=admin&quot;));
`}&lt;/p&gt;
&lt;p&gt;Real tools do this against real hashes. The canonical &lt;code&gt;hash_extender&lt;/code&gt; demonstrates it on MD5: publish &lt;code&gt;signature = MD5(secret || &quot;data&quot;) = 6036708eba0d11f6ef52ad44e8b74d5b&lt;/code&gt;, and knowing only &lt;code&gt;data&lt;/code&gt;, the algorithm, and that signature, an attacker loads the signature back into MD5&apos;s state and continues hashing a chosen suffix to forge a valid tag for &lt;code&gt;secret || data || glue || suffix&lt;/code&gt;, never learning the secret. Its own summary is the whole lesson: &quot;100% of the state needed to continue a hash is in the output of most hashing algorithms&quot; [@hash-extender].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; On any full-width Merkle-Damgard hash, including MD5, SHA-1, SHA-256, and SHA-512, the prefix-secret construction &lt;code&gt;H(secret || message)&lt;/code&gt; is forgeable by length extension. Use HMAC (Section 9) or a length-extension-immune hash instead. This footgun is common enough that it has its own family of real exploits in serialized-signing and token systems, examined in &lt;a href=&quot;https://paragmali.com/blog/the-signature-was-valid-the-message-was-forged-a-field-guide&quot; rel=&quot;noopener&quot;&gt;the serialization and canonicalization field guide&lt;/a&gt;; here we own the mechanism, that guide owns the exploitation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A precise note you should carry forward, because it is the sharpest discriminator between functions in this whole article. Length extension afflicts hashes whose digest exposes the full final state: MD5, SHA-1, and the full-width SHA-256 and SHA-512. Truncation can close the leak, but only if it hides enough of the state. The truncated SHA-2 variants that hide at least 128 bits (SHA-384, SHA-512/224, SHA-512/256), the SHA-3 family and SHAKE, HMAC, and the BLAKE hashes are all immune. The dangerous middle case is SHA-224, which discards only 32 bits and is therefore still vulnerable at about $2^{32}$ work, a distinction Section 6 makes exact. Defer the full table there; just remember that &quot;truncated&quot; does not automatically mean &quot;safe.&quot;&lt;/p&gt;
&lt;p&gt;The other three leaks are subtler but drove the field toward new designs. In 2004, Antoine Joux showed that in any iterated hash, finding $2^k$ messages that all share one digest costs only about $k$ times the work of a single collision, not the vastly larger amount naive counting suggests [@joux-crypto04]. The construction is almost embarrassingly direct: from the starting state, one birthday search finds a colliding pair of blocks that both drive the chain to the same next state; repeat from that state $k$ times; then every one of the $2^k$ ways to pick one block or the other at each step traces the identical chain to the identical final digest.&lt;/p&gt;
&lt;p&gt;These multicollisions demolish a piece of folklore that had reassured a generation of engineers: that concatenating two independent hashes, $H_1(m) ,|, H_2(m)$, multiplies their strength. It does not. Build a large multicollision in the weaker half -- many messages that all share one digest under it, which is cheap for a Merkle-Damgard hash -- then birthday-search that set for a pair that also collides under the stronger half. The combined collision resistance is essentially that of the stronger single hash, not the sum. Hashing twice buys almost nothing.&lt;/p&gt;
&lt;p&gt;Joux&apos;s multicollisions were also the engine for two deeper results. In 2005, John Kelsey and Bruce Schneier used expandable messages built from multicollisions to find second preimages on Merkle-Damgard hashes for far less than the ideal $2^n$: for a target of $2^k$ blocks, the cost falls to roughly $2^{n-k}$ plus overhead [@kelsey-schneier-eurocrypt05]. That matters because second-preimage resistance was supposed to be the sturdy $2^n$ clause, yet the shape leaks it for long messages. In 2006, Kelsey and Tadayoshi Kohno went further with the herding, or Nostradamus, attack: an attacker precomputes a branching diamond structure, publicly commits to a digest as if it were a prediction, and later herds almost any chosen prefix into that exact digest [@kelsey-kohno-eurocrypt06]. It weaponizes the construction into proof-of-prediction fraud.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Length extension, Joux multicollisions, long-message second preimages, and herding are flaws in the shape, not in the function. A stronger or longer compression function cannot fix them, because they do not depend on any weakness in that function. Only a different construction can. Hold that thought: it is exactly why, after the failures, the field did not just build a bigger Merkle-Damgard hash. It built a different machine.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Those four are leaks in an idealized world, where the compression function is flawless. They were serious enough to motivate truncated designs and, eventually, entirely new constructions. But they were still theoretical. What turned this subject from a seminar into a decade of emergency migrations was the other kind of failure: the compression function itself fell, and someone chose to weaponize it.&lt;/p&gt;
&lt;h2&gt;5. The Failure Catalog: Every Notable Break, Named&lt;/h2&gt;
&lt;p&gt;A broken hash is a lab curiosity until someone forges a certificate with it. Twice, someone did, and once it was a nation-state. This section is the heart of the guide, because the two failure arcs, MD5 and SHA-1, are the evidence for everything the rest of it recommends. Each arc runs the same course: a theoretical crack, a practical collision, a technique that makes the collision meaningful, and finally a real forged trust anchor.&lt;/p&gt;
&lt;p&gt;The MD5 arc opens with an early warning that the field under-heeded. In 1996, Hans Dobbertin found practical full collisions for MD4 and collisions in MD5&apos;s compression function under a chosen initial value, not yet the full hash but a clear structural crack [@dobbertin-md4]. MD5 stayed deployed anyway.&lt;/p&gt;
&lt;p&gt;The warning became undeniable in August 2004, when Xiaoyun Wang, Dengguo Feng, Xuejia Lai, and Hongbo Yu announced full MD5 collisions computable in minutes, alongside collisions for MD4, HAVAL-128, and RIPEMD [@wang-md5-eprint-2004-199]. The following year, Wang and Yu published the peer-reviewed differential method behind it [@wang-yu-break-md5-eurocrypt05]. That is the theoretical death of MD5. Everything after is engineering.&lt;/p&gt;
&lt;p&gt;The engineering that mattered was learning to choose the colliding inputs.&lt;/p&gt;

A collision between two inputs that begin with two different, attacker-chosen prefixes. The attacker fixes meaningful, distinct starting content for each side, two different names in a certificate, say, and then computes collision blocks that drive both sides to the same digest. This is strictly harder than an identical-prefix collision, where the two inputs share a common start, and strictly more dangerous, because it forges a relationship between two meaningful documents rather than two random blobs.
&lt;p&gt;In 2007, Marc Stevens, Arjen Lenstra, and Benne de Weger built exactly that for MD5, and used it to construct two X.509 certificates with different identities but the same MD5 digest [@stevens-chosen-prefix-md5-eurocrypt07].&lt;/p&gt;
&lt;p&gt;A year later the attack left the lab. At the 2008 Chaos Communication Congress, a seven-person team used a chosen-prefix MD5 collision, about $2^{49}$ MD5 compressions on a cluster of roughly 200 PlayStation 3 consoles, to obtain a genuine commercial certificate-authority signature over a benign certificate that simultaneously validated a forged intermediate certificate authority [@rogue-ca]. The forged certificate carried the basic-constraints CA flag set to TRUE, which meant every browser on earth would trust certificates it issued.&lt;/p&gt;

flowchart TD
    P1[&quot;Benign prefix: an ordinary certificate request&quot;] --&amp;gt; COL[&quot;Collision blocks appended to both sides&quot;]
    P2[&quot;Malicious prefix: a rogue CA certificate&quot;] --&amp;gt; COL
    COL --&amp;gt; SAME[&quot;Both certificates share one MD5 digest&quot;]
    SAME --&amp;gt; SIG[&quot;Commercial CA signs the benign certificate&quot;]
    SIG --&amp;gt; VALID[&quot;The same signature validates the rogue CA:TRUE certificate&quot;]
&lt;p&gt;To make two certificates collide, the attacker needs somewhere to park the roughly 1632-bit collision block without it looking suspicious. In the 2008 rogue CA, that space lived inside a &quot;Netscape Comment&quot; extension, a field parsers ignore, which the researchers wryly described as hiding the collision like a tumor inside an otherwise healthy certificate [@rogue-ca]. The lesson generalizes: any format with an ignorable, attacker-controlled field gives a collision attack room to breathe.&lt;/p&gt;
&lt;p&gt;The arc peaked in June 2012 with Flame, espionage malware that carried a code-signing certificate chaining to Microsoft. Flame&apos;s authors mounted a new chosen-prefix MD5 collision against a Microsoft sub-authority still using MD5 in its licensing service, letting them sign malware as &quot;Microsoft&quot; and distribute it through Windows Update. Marc Stevens later reconstructed the previously unknown collision variant from the certificate itself [@stevens-counter-cryptanalysis-crypto13].&lt;/p&gt;
&lt;p&gt;A nation-state had used a hash collision to subvert the update trust root of a billion machines. After Flame, MD5 in signatures was not deprecated as a matter of hygiene; it was radioactive.&lt;/p&gt;
&lt;p&gt;SHA-1 traveled the same road a decade behind. In 2005, Xiaoyun Wang, Yiqun Lisa Yin, and Hongbo Yu published the first collision attack on the full SHA-1, at about $2^{69}$ operations, comfortably under the $2^{80}$ birthday bound its 160-bit output was supposed to guarantee [@wang-yin-yu-full-sha1-crypto05]. That theoretical break is what prompted NIST to open the SHA-3 competition. The practical break took twelve more years of hardware progress. In February 2017, a team from CWI Amsterdam and Google announced SHAttered: the first practical identical-prefix SHA-1 collision, at roughly $2^{63.1}$ SHA-1 computations, about nine quintillion of them, costing the equivalent of 6,500 CPU-years plus 110 GPU-years [@shattered]. The proof was the pair of PDFs from this article&apos;s opening, sharing the digest &lt;code&gt;38762cf7f55934b34d179ae6a4c80cadccbb7f0a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In January 2020, Gaetan Leurent and Thomas Peyrin closed the arc with &quot;SHA-1 is a Shambles,&quot; the first practical chosen-prefix SHA-1 collision at about $2^{63.4}$, which along the way cut the identical-prefix cost to about $2^{61.2}$ [@shambles, @shambles-eprint-2020-014]. To prove it mattered, they forged a PGP/GnuPG key certification, tracked as CVE-2019-14855, building on their own EUROCRYPT 2019 precursor that first pushed collisions toward chosen prefixes [@leurent-peyrin-cp-eurocrypt19].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; SHAttered (2017) was an identical-prefix collision: both files began the same way. Shambles (2020) was a chosen-prefix collision: the two inputs started with different, meaningful content, which is what enables impersonation and forged certificates. Different authors, different years, strictly different strength. Conflating them is one of the most common errors in write-ups of SHA-1&apos;s demise.&lt;/p&gt;
&lt;/blockquote&gt;

&quot;All attacks that are practical on MD5 are now also practical on SHA-1.&quot; That is the Shambles team&apos;s own summary of what a chosen-prefix collision means: SHA-1 has caught down to MD5 [@shambles].

timeline
    title Two failure arcs, MD5 and SHA-1
    1996 : Dobbertin cracks MD4, dents the MD5 compression function
    2004 : Wang team announces practical full MD5 collisions
    2005 : Wang, Yin, Yu attack full SHA-1 near 2 to the 69
    2007 : Stevens builds chosen-prefix MD5 collisions
    2008 : Rogue certificate authority forged near 2 to the 49
    2012 : Flame forges a Microsoft-chained code-signing certificate
    2017 : SHAttered, first identical-prefix SHA-1 collision
    2020 : Shambles, first chosen-prefix SHA-1 collision
&lt;p&gt;The attack costs are worth tabulating, because they show how a break moves from theory to a weekend on rented hardware.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Break&lt;/th&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Attack type&lt;/th&gt;
&lt;th&gt;Approx. cost&lt;/th&gt;
&lt;th&gt;Real-world impact&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Rogue CA&lt;/td&gt;
&lt;td&gt;2008&lt;/td&gt;
&lt;td&gt;Chosen-prefix MD5&lt;/td&gt;
&lt;td&gt;$2^{49}$&lt;/td&gt;
&lt;td&gt;Forged intermediate CA trusted by browsers [@rogue-ca]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flame&lt;/td&gt;
&lt;td&gt;2012&lt;/td&gt;
&lt;td&gt;Chosen-prefix MD5&lt;/td&gt;
&lt;td&gt;new variant&lt;/td&gt;
&lt;td&gt;Forged Microsoft-chained code-signing cert [@stevens-counter-cryptanalysis-crypto13]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SHAttered&lt;/td&gt;
&lt;td&gt;2017&lt;/td&gt;
&lt;td&gt;Identical-prefix SHA-1&lt;/td&gt;
&lt;td&gt;$2^{63.1}$&lt;/td&gt;
&lt;td&gt;Two PDFs, one SHA-1 digest [@shattered]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shambles&lt;/td&gt;
&lt;td&gt;2020&lt;/td&gt;
&lt;td&gt;Chosen-prefix SHA-1&lt;/td&gt;
&lt;td&gt;$2^{63.4}$&lt;/td&gt;
&lt;td&gt;Forged PGP/GnuPG key certification [@shambles]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;There is a discipline the headlines miss, and it protects you from over-correcting. &quot;MD5 and SHA-1 are dead&quot; is true only for uses that depend on collision resistance.&lt;/p&gt;

Every break above attacks collision resistance. None of them touches HMAC-SHA-1 or HMAC-MD5, because HMAC does not rely on collision resistance at all, a point RFC 2104 made in 1997 and Section 9 unpacks [@rfc-2104]. So the correct scoping is narrow: MD5 and SHA-1 are dead where an adversary can influence the hashed input and profit from a collision, above all in signatures and certificates. They are not magically extinct. Old certificate chains, legacy protocols, and Git&apos;s historical use of SHA-1 all persist, which is why NIST set a firm calendar date, the end of 2030, to withdraw SHA-1 from all U.S. government use rather than pretending it vanished overnight [@nist-retires-sha1]. The recurring lesson of both arcs: deprecating an algorithm in new code is not the same as revoking it from live trust anchors.
&lt;p&gt;Every hash in this catalog shared one design shape, the Merkle-Damgard chain of Section 3. The obvious question, and the one the field actually asked, was whether anything built the same way survived. One did, and understanding why is the turn from despair to design.&lt;/p&gt;
&lt;h2&gt;6. The Survivor: SHA-2, and Why It Did Not Fall&lt;/h2&gt;
&lt;p&gt;Here is a paradox worth sitting with. SHA-2 is built the same way as SHA-1: the same Merkle-Damgard skeleton, the same add-rotate-xor compression style, designed by the same institution. By the logic of the last two sections it should have fallen too. Instead, in 2026, SHA-256 is the hash under most of the internet. What did the survivors do differently?&lt;/p&gt;
&lt;p&gt;The family, standardized in FIPS 180-4, has six members: SHA-224, SHA-256, SHA-384, and SHA-512, plus the truncated SHA-512/224 and SHA-512/256 [@fips-180-4]. And the answer to the paradox is almost anticlimactic. SHA-2 did not adopt a new idea. It widened the margins of the old one.&lt;/p&gt;
&lt;p&gt;Larger chaining state, a longer and more diffusing message schedule, more rounds, and distinct per-round constants together mean that the differential paths Wang&apos;s team rode through MD5 and SHA-1 do not propagate far enough to reach the full function. The evidence is two decades of cryptanalysis that keeps stalling short: the best published collision attacks reach only 31 of SHA-256&apos;s 64 rounds in practice [@mendel-nad-schlaffer-eurocrypt13], and 39 rounds in the weaker semi-free-start setting [@li-liu-wang-sha2-2024]. A 2024 effort using programmatic SAT solvers likewise reaches only reduced-round or modified-initial-value variants, never the full function [@sha256-sat-2024]. That wide margin, 33 rounds to the deepest true collision and 25 even against the weaker semi-free-start attack, is the entire reason to trust it.&lt;/p&gt;
&lt;p&gt;There is one wrinkle the designers half-anticipated, and it is the single most useful discriminator you can memorize. Full-width SHA-256 and SHA-512 are length-extension-vulnerable, exactly as Section 4 warned, because their digest is the whole final state. Most of the truncated members are not. But one truncated member still is, and it is the one people most often get wrong.&lt;/p&gt;

A hash whose internal chaining state is wider than its emitted output, so the digest reveals only part of the final state. SHA-384 and SHA-512/256 run the full SHA-512 engine, a 512-bit state, but output only 384 or 256 bits. Because an attacker never sees the whole state, length extension has nothing to resume from, provided enough of the state stays hidden.
&lt;p&gt;The catch is in that last clause. Truncation defeats length extension only when the hidden part of the state is too large to guess. SHA-384 hides 128 bits and SHA-512/256 hides 256; recovering either by brute force is infeasible. SHA-224, however, is SHA-256 with a different initial value and the 256-bit result cut to 224 bits, so it discards only one 32-bit word of state [@rfc-3874].&lt;/p&gt;
&lt;p&gt;An attacker brute-forces that missing 32 bits in about $2^{32}$ compression calls, seconds on commodity hardware, recovers the full internal state, and then length-extends exactly as if nothing were hidden. SHA-224 is therefore length-extension-vulnerable with only a 32-bit margin, categorically different from the truncated variants that hide 128 bits or more.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The move that saves SHA-384 and SHA-512/256 is almost embarrassingly simple: hide part of the final state. But the amount hidden is the whole game. Hide 128 or 256 bits and length extension has nothing feasible to resume from. Hide only 32 bits, as SHA-224 does, and an attacker recovers the state in about $2^{32}$ work and extends normally. &quot;Truncated&quot; is not a synonym for &quot;safe&quot;; &quot;truncated by enough&quot; is. The sponge, next section, takes this instinct to its logical end by never exposing the state at all.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The table below is the sharpest single reference in this guide. When someone asks whether a hash is safe to use as &lt;code&gt;H(secret || message)&lt;/code&gt;, this is the answer.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Length-extension vulnerable&lt;/th&gt;
&lt;th&gt;Length-extension immune&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;MD5, SHA-1&lt;/td&gt;
&lt;td&gt;SHA-384&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SHA-256, SHA-512 (full-width)&lt;/td&gt;
&lt;td&gt;SHA-512/224, SHA-512/256&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SHA-224 (only $2^{32}$ margin)&lt;/td&gt;
&lt;td&gt;SHA-3 family and SHAKE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;HMAC (any hash), BLAKE2, BLAKE3, KangarooTwelve&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;SHA-NI, the x86 hash instructions Intel and AMD ship, accelerate SHA-1 and SHA-256 but not SHA-512 [@intel-sha-extensions]. That inverts an old piece of folklore. For years SHA-512 was &quot;the fast one&quot; on 64-bit CPUs because it processes 64-bit words; on a 2023 AMD Zen 4, SHA-256 now runs at about 2.03 cycles per byte while SHA-512 trails at about 4.19, because only SHA-256 gets the hardware boost [@ebash-zen4]. On CPUs without SHA-NI, the old ordering returns and SHA-512 and SHA-512/256 pull ahead again.&lt;/p&gt;
&lt;p&gt;That hardware acceleration, combined with universal library support and FIPS validation, is why SHA-256 is the correct default almost everywhere its deployment footprint shows: TLS 1.3 computes its handshake transcript hash with the negotiated SHA-256 or SHA-384 [@rfc-8446], Bitcoin hashes every block header with double SHA-256 [@bitcoin-block-hashing], and Git&apos;s next-generation object format is built on SHA-256 [@git-sha256-transition], alongside code-signing digests and certificate fingerprints. It earned that position not by being newest but by being unbroken and fast where it counts.&lt;/p&gt;
&lt;p&gt;Keep one framing straight, because the whole next act depends on it. SHA-2 is a survivor of the supersession arc that ran MD5 to SHA-1 to SHA-2. It is not something a later hash replaced. But a healthy survivor carrying most of the world&apos;s traffic is still a monoculture, and the field had just learned, viscerally, what happens when everything rests on one design. So even though SHA-2 was fine, cryptographers deliberately built something that shared none of its DNA.&lt;/p&gt;
&lt;h2&gt;7. The Different Shape: The Sponge and SHA-3&lt;/h2&gt;
&lt;p&gt;Imagine a hash with no exposed chaining state to steal, that hands you arbitrary-length output for free, and that shares no mathematical DNA with SHA-2. That is not a patch on Merkle-Damgard. It is a different machine.&lt;/p&gt;
&lt;p&gt;NIST went looking for that machine deliberately. In November 2007, stung by the 2004 and 2005 collision attacks, it opened a public SHA-3 competition, explicitly asking for a hash built on a construction unlike SHA-2 so that a future break of one would not endanger the other [@nist-sha3-project]. Five finalists emerged from dozens of submissions: BLAKE, Grostl, JH, Keccak, and Skein. In October 2012, NIST selected Keccak, designed by Guido Bertoni, Joan Daemen, Michael Peeters, and Gilles Van Assche, and standardized it as FIPS 202 in August 2015 [@nist-sha3-project, @fips-202]. Its engine is the sponge.&lt;/p&gt;

A hash built around a single fixed permutation applied to a state of $b$ bits, split into a rate of $r$ bits and a capacity of $c$ bits, with $b = r + c$. In the absorb phase, message blocks are XORed into the rate portion and the whole state is stirred by the permutation. In the squeeze phase, output bytes are read from the rate, with the permutation applied between reads. The capacity is never read from or written to directly. SHA-3 uses the Keccak permutation on a 1600-bit state over 24 rounds.
&lt;p&gt;The capacity is the whole trick. Because those $c$ bits never touch the input or the output, an attacker who sees the digest learns nothing about them, and cannot reconstruct the internal state.&lt;/p&gt;

flowchart LR
    M[&quot;Message blocks&quot;] --&amp;gt; ABS[&quot;Absorb: XOR into rate, then permute&quot;]
    ABS --&amp;gt; STATE[&quot;State: rate lane plus capacity lane&quot;]
    STATE --&amp;gt; SQ[&quot;Squeeze: read the rate, permute, repeat&quot;]
    SQ --&amp;gt; OUT[&quot;Output: fixed digest or an XOF stream&quot;]
    CAP[&quot;Capacity lane, never read or written directly&quot;] -.-&amp;gt; STATE
&lt;p&gt;Two payoffs fall out of that single design decision. First, the sponge is length-extension-immune by construction, not by truncation: there is no exposed final state to resume from, so &lt;code&gt;H(secret || message)&lt;/code&gt; is not forgeable the way it is on full-width SHA-2. Second, the squeeze phase can simply keep going, so the sponge is natively an extendable-output function.&lt;/p&gt;

A hash-like primitive that emits output of any length you ask for from a single input, rather than a fixed-size digest. You request as many bytes as you need and keep squeezing. SHAKE128 and SHAKE256, standardized alongside SHA-3, are the workhorse examples, and they are what modern post-quantum schemes call to expand seeds into keys.
&lt;p&gt;The security is not folklore. Bertoni, Daemen, Peeters, and Van Assche proved the sponge is indifferentiable from a random oracle up to the capacity bound, which is the strongest positive statement you can make about a concrete construction [@bertoni-sponge-indiff-eurocrypt08, @keccak-sponge-duplex]. In two decades of analysis, practical collisions have reached only about 5 of Keccak&apos;s 24 rounds, leaving an enormous margin [@keccak-third-party].&lt;/p&gt;
&lt;p&gt;Now the load-bearing correction this whole guide exists to make. SHA-3 is not the successor to SHA-2 the way SHA-2 succeeded SHA-1. FIPS 202 chooses its words carefully.&lt;/p&gt;

FIPS 202 states that the four SHA-3 functions &quot;supplement the hash functions ... in FIPS 180-4: SHA-1 and the SHA-2 family,&quot; and that together the two standards &quot;provide resilience against future advances&quot; because they &quot;rely on fundamentally different design principles&quot; [@fips-202].
&lt;p&gt;The word is supplement, not supersede, and NIST is even blunter elsewhere: its Policy on Hash Functions says there is &quot;no need to transition applications from SHA-2 to SHA-3&quot; [@nist-policy-hash-functions], and the superseded 2012 version of that policy put it more strongly still, with &quot;no need or plan to transition&quot; [@nist-policy-hash-functions-2012-archived].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; SHA-3 is not the replacement for SHA-2. It is the insurance policy. After watching one construction, Merkle-Damgard, carry MD5, SHA-1, and SHA-2 all at once, the field deliberately funded a second, unrelated construction so that the internet&apos;s trust machinery would never again rest on a single design. SHA-2 and SHA-3 coexist on purpose. That is diversification, not supersession, and it is a different axis from the MD5-to-SHA-1-to-SHA-2 ladder entirely.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ethereum uses &quot;Keccak-256,&quot; which is the original competition-era Keccak with its pre-standard padding, not the FIPS 202 SHA3-256 that NIST later finalized with an extra domain-separation suffix. The two give different digests for the same input, a frequent source of confusion for developers who assume &quot;Keccak&quot; and &quot;SHA-3&quot; are interchangeable. Solidity&apos;s built-in is spelled &lt;code&gt;keccak256&lt;/code&gt; precisely to signal the original variant [@solidity-globals].&lt;/p&gt;
&lt;p&gt;The sponge bought genuine algorithmic diversity and length-extension immunity for free. What it did not buy, at least in plain software, was raw speed: on a Zen 4 core without special instructions, SHA3-256 runs at about 6.8 cycles per byte, roughly three times slower than hardware-accelerated SHA-256 [@ebash-zen4]. That gap set the agenda for the last decade. Could you keep the security and the length-extension immunity and still go an order of magnitude faster? Two answers arrived, from two different shapes.&lt;/p&gt;
&lt;h2&gt;8. The Fast Hashes: BLAKE3, the Tree, and Where K12 Sits&lt;/h2&gt;
&lt;p&gt;The command &lt;code&gt;b3sum&lt;/code&gt; can hash a large file roughly ten times faster than &lt;code&gt;sha256sum&lt;/code&gt;, and it does not cheat to get there [@blake3-repo]. It uses every CPU core and every SIMD lane at once. Understanding how it does that, and when you should let it, means separating two ideas people constantly conflate.&lt;/p&gt;
&lt;p&gt;There are two axes here, and they are independent. The construction axis says how a hash is built: Merkle-Damgard (SHA-2), sponge (SHA-3, SHAKE, and, importantly, KangarooTwelve), and the BLAKE tree family derived from the ChaCha stream cipher. The use-case axis says what job you are hiring it for, and &quot;modern high-throughput hash&quot; is a job, currently filled by BLAKE3 and KangarooTwelve. Notice that those two fast hashes sit on different construction axes: one is a tree over an ARX core, the other is a sponge. Speed is not a construction.&lt;/p&gt;
&lt;p&gt;The BLAKE line began as a SHA-3 finalist, a ChaCha-derived design [@hash-function-blake-book]. It became practical with BLAKE2, specified in RFC 7693, which is directly keyable: feed it a key and it is a message authentication code with no HMAC wrapper needed [@rfc-7693]. Then in 2020, Jack O&apos;Connor, Jean-Philippe Aumasson, Samuel Neves, and Zooko Wilcox-O&apos;Hearn released BLAKE3, which took the decisive structural step: it arranges a round-reduced BLAKE2-style compression function inside a binary Merkle tree [@blake3-repo].&lt;/p&gt;

flowchart TD
    ROOT[&quot;Root chaining value, extensible to an XOF&quot;] --&amp;gt; P0[&quot;Parent node&quot;]
    ROOT --&amp;gt; P1[&quot;Parent node&quot;]
    P0 --&amp;gt; L0[&quot;Chunk 0, 1 KiB&quot;]
    P0 --&amp;gt; L1[&quot;Chunk 1, 1 KiB&quot;]
    P1 --&amp;gt; L2[&quot;Chunk 2, 1 KiB&quot;]
    P1 --&amp;gt; L3[&quot;Chunk 3, 1 KiB&quot;]
&lt;p&gt;The tree is what unlocks the speed. Because each 1 KiB chunk hashes independently, any number of SIMD lanes and threads can work in parallel, and the results combine afterward. The same structure gives BLAKE3 incremental updates and verified streaming, and it collapses five roles into one function: plain hash, keyed MAC, pseudorandom function, key-derivation function via its &lt;code&gt;derive_key&lt;/code&gt; mode, and extendable output. On a Zen 4 core it runs at about 0.60 cycles per byte single-threaded, the fastest secure hash in the eBASH benchmarks, before you even add threads [@ebash-zen4].&lt;/p&gt;

BLAKE3&apos;s own documentation states it plainly: it is &quot;secure against length extension, unlike SHA-2&quot; [@blake3-repo].
&lt;p&gt;The 1 KiB chunk size is not arbitrary. Because every chunk is an independent leaf, a verifier holding the root can check that one specific 1 KiB slice of a huge file is authentic by recomputing only the $O(\log n)$ nodes along its path, never re-hashing the whole file. That is the basis of verified streaming: download a movie and verify each piece as it arrives, aborting instantly if any block is corrupted or tampered [@blake3-repo].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; BLAKE3 is engineered to be fast, which makes it exactly wrong for hashing passwords, where you want to be deliberately slow so an attacker cannot try billions of guesses per second. Its own README says as much and points you to Argon2 [@blake3-repo]. Use a purpose-built password KDF, Argon2id for new systems, or scrypt, bcrypt, or PBKDF2, never a bare fast hash. Section 11 returns to this.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The other fast hash keeps you on the sponge. KangarooTwelve, with its TurboSHAKE core, is a tree hash over a round-reduced Keccak permutation, Keccak-p with 12 rounds instead of 24, published as the Informational RFC 9861 in October 2025 [@rfc-9861, @k12-acns18]. It is genuinely fast: the vendor reports about 0.51 cycles per byte using AVX-512 and 0.75 on an Apple M1, though a generic build measures closer to 3.5 cycles per byte on Zen 4 [@keccak-kangarootwelve, @ebash-zen4]. The point to hold onto, and the reason it gets a signpost rather than a section, is that KangarooTwelve is not a third construction family. It is the sponge again, tuned for throughput. It is standardized but still niche, and, like BLAKE3, not FIPS-approved.&lt;/p&gt;

On a machine with both tools installed, `time b3sum bigfile.iso` against `time sha256sum bigfile.iso` on a multi-gigabyte file shows the order-of-magnitude gap the BLAKE3 documentation advertises, most of it from multithreading. If you only have OpenSSL, `openssl dgst -sha3-256 bigfile.iso` will show you the software sponge penalty on hardware without SHA-3 instructions.
&lt;p&gt;Everything else is a one-line signpost. RIPEMD-160, Whirlpool, China&apos;s SM3, and Russia&apos;s Streebog are real and occasionally mandated regionally, but they are not the default anywhere the reader is likely to design for. The losing SHA-3 finalists, Grostl, JH, and Skein, are well-analyzed but standardized nowhere. None of them changes the decision you are about to make.&lt;/p&gt;
&lt;p&gt;Fast, parallel, and diverse, yes. But so far we have only hashed raw data. Real protocols almost never use a bare hash. They key it, they separate its domains, and they stretch its output, and that is precisely where most real bugs live.&lt;/p&gt;
&lt;h2&gt;9. Beyond the Bare Hash: Keyed, Domain-Separated, and XOF Modes&lt;/h2&gt;
&lt;p&gt;The most common hash bug in production is not a broken algorithm. It is a correct algorithm used in the wrong mode, and the specific mistake, again and again, is pressing &lt;code&gt;H(secret || message)&lt;/code&gt; into service as a message authentication code. Section 4 showed why that is forgeable on full-width SHA-2. Here is what to use instead, and why it holds.&lt;/p&gt;
&lt;p&gt;The canonical fix is HMAC, from Mihir Bellare, Ran Canetti, and Hugo Krawczyk in 1996 and RFC 2104 in 1997 [@bellare-canetti-krawczyk-crypto96, @rfc-2104].&lt;/p&gt;

A message authentication code built from any hash $H$ and a secret key $K$ by nesting two hash calls: $$\mathrm{HMAC}(K, m) = H\big((K \oplus opad) \,\|\, H((K \oplus ipad) \,\|\, m)\big)$$ where $opad$ and $ipad$ are fixed padding constants. Bellare, Canetti, and Krawczyk proved it is a secure pseudorandom function under assumptions weaker than full collision resistance of $H$.
&lt;p&gt;Two things make HMAC the right tool. First, the outer hash of an inner hash structurally defeats length extension: the attacker never sees a resumable state. Second, and this is the payoff of the scoping discipline from Section 5, HMAC does not depend on the collision resistance of its hash. RFC 2104 states directly that the known collision weaknesses of MD5 &quot;do not compromise the use of MD5 within HMAC&quot; [@rfc-2104]. That is why HMAC-SHA-1 and HMAC-MD5 remain unbroken even though bare SHA-1 and MD5 are dead for signatures.&lt;/p&gt;
&lt;p&gt;The keys HMAC needs have to come from somewhere with real entropy, which is the subject of Part 2 of this series, &lt;a href=&quot;https://paragmali.com/blog/predictable-or-repeated-the-only-two-ways-cryptographic-rand&quot; rel=&quot;noopener&quot;&gt;the field guide to cryptographic randomness&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;HMAC is also the foundation of the most widely deployed key-derivation function, HKDF, which follows an extract-then-expand pattern: an extract step distills a uniform key from messy input keying material, and an expand step stretches it to any needed length [@rfc-5869]. HKDF is worth naming precisely because it is a mode built on a hash by way of HMAC, not a hash itself; when you need to turn a shared secret into keys, reach for it rather than hashing by hand.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you need to authenticate a message with a key, reach for &lt;code&gt;HMAC-SHA-256&lt;/code&gt; or &lt;code&gt;KMAC&lt;/code&gt;. Do not invent &lt;code&gt;H(key || message)&lt;/code&gt;, &lt;code&gt;H(message || key)&lt;/code&gt;, or any variation: the first is length-extension-forgeable on full-width SHA-2, and the others have their own pitfalls that decades of analysis went into avoiding. The whole point of HMAC and KMAC is that someone already did the hard work and proved it correct.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The sponge offers a native alternative that needs no nesting, because it already resists length extension. NIST SP 800-185 defines four such functions: cSHAKE, KMAC, TupleHash, and ParallelHash [@sp-800-185]. KMAC is a keyed MAC that simply absorbs the key into the sponge. The other three are about domain separation.&lt;/p&gt;

Deliberately making the hash of the same bytes come out different depending on the context in which they appear, by mixing in a distinct label or customization string per context. It stops an input crafted for one purpose from being replayed as a valid input to another.

Consider hashing a pair of fields, a username and a message. Concatenating them and hashing, `H(user || message)`, is ambiguous: the pair (`alice`, `bob-says-hi`) and the pair (`aliceb`, `ob-says-hi`) serialize to the same bytes and therefore the same digest. An attacker who controls where the boundary falls can forge equivalences. TupleHash removes the ambiguity by length-encoding each element of the sequence, so the structure, not just the bytes, is bound into the digest. cSHAKE does the same across protocol contexts: a customization string like the ASCII label for &quot;email-signature&quot; versus &quot;file-checksum&quot; guarantees the two contexts can never produce the same output for the same input. Any time distinct inputs could serialize to identical byte streams, you need this, and rolling it yourself is where subtle bugs breed [@sp-800-185].
&lt;p&gt;XOFs change how you get short outputs, too. If you need a 20-byte value at a 128-bit security level, do not hash and chop arbitrary bytes off SHA-256; ask SHAKE128 or a BLAKE3 XOF for exactly 20 bytes. The security level is governed by the capacity, not by how many bytes you happen to read, so requesting the exact length is both cleaner and safer than ad hoc truncation. NIST is even revising SP 800-185 to add streaming specifications for SHAKE, a sign of how central XOFs have become [@nist-fips202-sp800185-update].&lt;/p&gt;
&lt;p&gt;Finally, the oldest mode of all scales integrity to enormous data: the Merkle tree from Ralph Merkle&apos;s 1979 thesis [@merkle-thesis-1979]. Hash the leaves, hash pairs of hashes upward to a single root, and you can prove any one leaf belongs to the root with a path of only $O(\log n)$ hashes. Git object trees, blockchain state commitments, Certificate Transparency logs, and BLAKE3&apos;s verified streaming are all this idea.&lt;/p&gt;
&lt;p&gt;The one rule that separates a correct Merkle tree from a broken one is to domain-separate leaf nodes from internal nodes, so an attacker cannot pass an internal node off as a leaf, exactly the flag-bit discipline BLAKE3 bakes in. The sponge and BLAKE families also power keyed authenticated-encryption modes, which belong to the block-cipher and nonce-reuse parts of this series and are out of scope here.&lt;/p&gt;
&lt;p&gt;We now have functions and modes that keep every clause of the promise. But every one of them still bows to a few hard mathematical ceilings, and to one machine that does not yet exist. How much should you actually worry?&lt;/p&gt;
&lt;h2&gt;10. Theoretical Limits: Bounds, the Random Oracle, and Quantum&lt;/h2&gt;
&lt;p&gt;There is a best-possible hash, and you cannot build it. Understanding exactly why is what separates fear from calibrated caution, especially about quantum computers.&lt;/p&gt;
&lt;p&gt;Start with the ceilings. For an ideal $n$-bit hash, collision resistance cannot exceed about $2^{n/2}$ work and preimage resistance cannot exceed about $2^{n}$. Those are not merely the best known attacks; they are the best any hash of that output length can offer, because the birthday and search arguments apply to a perfect random function. The good news, easy to miss, is that the deployed survivors meet those bounds exactly. The best published attack on full SHA-256, SHA-512, SHA3-256, BLAKE2, and BLAKE3 is the generic one, so there is no gap between what an attacker can do and the theoretical floor.&lt;/p&gt;
&lt;p&gt;When cryptographers talk about a function&apos;s &quot;security margin,&quot; they mean something narrower and attack-specific: the unbroken rounds between the deepest cryptanalysis of a given kind and the full round count. For SHA-256 collisions, published attacks reach 31 of 64 rounds (39 in the weaker semi-free-start setting), leaving a wide margin [@mendel-nad-schlaffer-eurocrypt13, @li-liu-wang-sha2-2024]; for Keccak collisions, only about 5 of 24 rounds fall [@keccak-third-party]. Wide margins are why these functions are trusted, not a gap in their strength.&lt;/p&gt;
&lt;p&gt;The one clause where an ideal is genuinely out of reach is the random oracle. A fixed, finite, publicly specified function cannot actually behave like a fresh random answer for every input, for the plain reason that its code is right there to analyze. Ran Canetti, Oded Goldreich, and Shai Halevi made this precise: there exist signature and encryption schemes provably secure in the random-oracle model for which every concrete instantiation of the oracle by a real hash yields an insecure scheme [@cgh-jacm-2004, @cgh-stoc-1998]. So the random-oracle model is a proof heuristic, not a guarantee.&lt;/p&gt;
&lt;p&gt;The reachable substitute is indifferentiability: the sponge is provably indifferentiable from a random oracle up to its capacity bound, which is the strongest honest claim a real construction can make [@bertoni-sponge-indiff-eurocrypt08]. And a related limit from Section 4 still bites: Antoine Joux&apos;s multicollisions mean concatenating two hashes does not multiply their strength, so there is no cheap &quot;hash twice&quot; route to a stronger oracle [@joux-crypto04].&lt;/p&gt;
&lt;p&gt;Now quantum, where the folklore is loudest and least accurate. Grover&apos;s algorithm gives a square-root speedup for search, so a quantum preimage on an $n$-bit hash costs about $2^{n/2}$ instead of $2^n$ [@grover-1996]. That halves the preimage exponent, which sounds alarming until you plug in numbers: SHA-256 keeps about 128 bits of preimage resistance against an ideal quantum adversary, still far beyond reach.&lt;/p&gt;
&lt;p&gt;Collisions are the subtler story. Brassard, Hoyer, and Tapp gave a quantum collision algorithm at about $2^{n/3}$ queries, but it demands a comparable amount of quantum-accessible memory [@brassard-hoyer-tapp-latin98]. Daniel Bernstein&apos;s cost analysis shows that once you charge honestly for that memory, plain parallel classical collision search at $2^{n/2}$ with cheap hardware wins, so the practical quantum speedup for collisions is marginal [@bernstein-sharcs09]. SHA-256 therefore keeps roughly 128-bit collision resistance in practice, quantum or not.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;Classical preimage&lt;/th&gt;
&lt;th&gt;Classical collision&lt;/th&gt;
&lt;th&gt;Quantum preimage (Grover)&lt;/th&gt;
&lt;th&gt;Quantum collision (practical)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;SHA-256&lt;/td&gt;
&lt;td&gt;$2^{256}$&lt;/td&gt;
&lt;td&gt;$2^{128}$&lt;/td&gt;
&lt;td&gt;$2^{128}$&lt;/td&gt;
&lt;td&gt;about $2^{128}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SHA-384&lt;/td&gt;
&lt;td&gt;$2^{384}$&lt;/td&gt;
&lt;td&gt;$2^{192}$&lt;/td&gt;
&lt;td&gt;$2^{192}$&lt;/td&gt;
&lt;td&gt;about $2^{192}$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SHA-512&lt;/td&gt;
&lt;td&gt;$2^{512}$&lt;/td&gt;
&lt;td&gt;$2^{256}$&lt;/td&gt;
&lt;td&gt;$2^{256}$&lt;/td&gt;
&lt;td&gt;about $2^{256}$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The claim &quot;quantum halves every security level&quot; is right for preimage and wrong for collisions. Halving the collision exponent from $2^{n/2}$ to $2^{n/3}$ would matter only if the required quantum memory were free, and it is not. Charge for it, as Bernstein does, and classical machines are more cost-effective at finding collisions, so the honest planning figure for SHA-256 collision resistance stays near 128 bits [@bernstein-sharcs09].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you want more headroom against a future quantum adversary, you do not need a different construction. You need more output bits. That is the entire reason NIST keeps SHA-384, SHA-512, and the 256-bit-security XOF SHAKE256 in the toolbox: they push both preimage and collision margins up by widening the digest. KT256, defined in the Informational IRTF RFC 9861 rather than a FIPS standard, offers the same raised margin outside the FIPS boundary [@rfc-9861]. The migration story for the rest of cryptography, where the fix really is new algorithms, is covered separately in &lt;a href=&quot;https://paragmali.com/blog/the-thirty-year-migration-ships-in-a-pip-install-how-post-qu&quot; rel=&quot;noopener&quot;&gt;the post-quantum migration guide&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Two frontiers sit just outside this guide&apos;s scope but deserve a pointer, because they are where hashes are heading. The first is arithmetization-oriented hashes such as Poseidon [@poseidon-usenix-sec21] and the Rescue and Vision family [@rescue-tosc-2020], designed to minimize arithmetic-circuit cost inside zero-knowledge proof systems rather than CPU cycles. They are younger, with far less mature cryptanalysis than SHA-2 or SHA-3, so they are a higher-risk choice outside their niche.&lt;/p&gt;
&lt;p&gt;The second runs the other direction: hash-based signatures such as LMS [@rfc-8554], XMSS [@rfc-8391], and the standardized stateless SLH-DSA [@fips-205] build post-quantum signatures purely from hash calls, so they consume this primitive rather than being one. Both belong to the post-quantum posts in this series, not here.&lt;/p&gt;
&lt;p&gt;So the mathematics delivers a calm verdict. The survivors are as strong as any hash of their output length can be, and quantum computers sharpen the analysis rather than overturning it. That means the last question is not &quot;which hash is strongest,&quot; because among the survivors none is meaningfully stronger than another. The question is which function, in which mode, for your specific job.&lt;/p&gt;
&lt;h2&gt;11. The Practical Guide: Choose X with These Params in Case Y&lt;/h2&gt;
&lt;p&gt;Everything so far collapses into one habit. Name the clause your protocol actually leans on, then pick the function and mode that keeps it. Here is that decision on a single page.&lt;/p&gt;

flowchart TD
    START[&quot;What is the job?&quot;] --&amp;gt; Q0{&quot;Passwords or low-entropy secrets?&quot;}
    Q0 --&amp;gt;|Yes| ARGON[&quot;Argon2id, or scrypt, bcrypt, PBKDF2&quot;]
    Q0 --&amp;gt;|No| Q1{&quot;Keyed authentication?&quot;}
    Q1 --&amp;gt;|Yes| HMAC[&quot;HMAC-SHA-256, or KMAC for the sponge&quot;]
    Q1 --&amp;gt;|No| Q2{&quot;FIPS approval required?&quot;}
    Q2 --&amp;gt;|No| BLAKE[&quot;BLAKE3 for throughput, streaming, and KDF&quot;]
    Q2 --&amp;gt;|Yes| Q3{&quot;Length-extension safety needed?&quot;}
    Q3 --&amp;gt;|Yes| TRUNC[&quot;SHA-512/256, or SHA-3 and SHAKE&quot;]
    Q3 --&amp;gt;|No| SHA256[&quot;SHA-256, the default&quot;]
&lt;p&gt;The head-to-head matrix fills in the details behind those leaves. Speeds are single-thread cycles per byte on a 2023 AMD Zen 4, from the eBASH measurements [@ebash-zen4]; every full function listed is unbroken, so the choice is driven by length-extension behavior, speed, FIPS status, and parallelism, not by any strength gap.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;Construction&lt;/th&gt;
&lt;th&gt;Output / security&lt;/th&gt;
&lt;th&gt;LE-safe&lt;/th&gt;
&lt;th&gt;Speed (cyc/B)&lt;/th&gt;
&lt;th&gt;FIPS&lt;/th&gt;
&lt;th&gt;Parallel&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;SHA-256&lt;/td&gt;
&lt;td&gt;Merkle-Damgard&lt;/td&gt;
&lt;td&gt;256 / 128 coll&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;2.03&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Default integrity, signatures, interop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SHA-512&lt;/td&gt;
&lt;td&gt;Merkle-Damgard&lt;/td&gt;
&lt;td&gt;512 / 256 coll&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;4.19&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;High margin on 64-bit software&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SHA-512/256&lt;/td&gt;
&lt;td&gt;Merkle-Damgard (trunc)&lt;/td&gt;
&lt;td&gt;256 / 128 coll&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;about 4.2&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;LE-immunity plus FIPS in software&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SHA3-256&lt;/td&gt;
&lt;td&gt;Sponge&lt;/td&gt;
&lt;td&gt;256 / 128 coll&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;6.81&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Construction diversity, LE-immune&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SHAKE128&lt;/td&gt;
&lt;td&gt;Sponge XOF&lt;/td&gt;
&lt;td&gt;any / 128 ceiling&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;5.43&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Variable-length output, PQC expansion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BLAKE2b&lt;/td&gt;
&lt;td&gt;ARX (HAIFA)&lt;/td&gt;
&lt;td&gt;512 / 256 coll&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;3.54&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Tree mode&lt;/td&gt;
&lt;td&gt;Fast keyed software hash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BLAKE3&lt;/td&gt;
&lt;td&gt;ARX Merkle tree&lt;/td&gt;
&lt;td&gt;256, XOF / 128&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;0.60&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;High-throughput integrity, KDF, streaming&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;KT128&lt;/td&gt;
&lt;td&gt;Sponge tree&lt;/td&gt;
&lt;td&gt;any / 128&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;about 3.5 (0.51 with AVX-512)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;High throughput on the Keccak basis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HMAC-SHA-256&lt;/td&gt;
&lt;td&gt;Nested keyed MD&lt;/td&gt;
&lt;td&gt;MAC / PRF&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;about 2x SHA-256&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Keyed authentication&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;KMAC256&lt;/td&gt;
&lt;td&gt;Keyed sponge&lt;/td&gt;
&lt;td&gt;any / 256&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;about SHAKE256&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Keyed plus domain-separated auth&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;And the same advice as a quick &quot;use / never&quot; card, the version you tape above your desk.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use this&lt;/th&gt;
&lt;th&gt;For this job&lt;/th&gt;
&lt;th&gt;Never use here&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;SHA-256&lt;/td&gt;
&lt;td&gt;Default integrity, signatures, interop&lt;/td&gt;
&lt;td&gt;MD5, SHA-1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SHA-512/256&lt;/td&gt;
&lt;td&gt;Length-extension immunity plus FIPS in software&lt;/td&gt;
&lt;td&gt;full-width &lt;code&gt;H(secret||msg)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SHA3-256 or SHAKE256&lt;/td&gt;
&lt;td&gt;Construction diversity, XOF, PQC seed expansion&lt;/td&gt;
&lt;td&gt;naive truncation of a fixed hash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BLAKE3&lt;/td&gt;
&lt;td&gt;High-throughput, streaming, KDF via &lt;code&gt;derive_key&lt;/code&gt; (non-FIPS)&lt;/td&gt;
&lt;td&gt;passwords&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HMAC-SHA-256 or KMAC&lt;/td&gt;
&lt;td&gt;Keyed authentication&lt;/td&gt;
&lt;td&gt;&lt;code&gt;H(key||msg)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Argon2id&lt;/td&gt;
&lt;td&gt;Passwords, low-entropy secrets&lt;/td&gt;
&lt;td&gt;any bare fast hash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MD5, CRC&lt;/td&gt;
&lt;td&gt;Non-security checksums only&lt;/td&gt;
&lt;td&gt;signatures, certs, deduplication&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;A few sizing rules turn those tables into correct code. For a target security level of $s$ bits against collisions, make the digest at least $2s$ bits, because collision resistance is only half the output length; 128-bit collision security therefore needs a 256-bit hash.&lt;/p&gt;
&lt;p&gt;When you need a non-standard output length, request it from an XOF (SHAKE, KMAC, or a BLAKE3 XOF) rather than truncating a fixed digest by hand, and remember that reading more XOF bytes never raises you above the capacity ceiling. Add margin, SHA-384, SHA-512, SHAKE256, or KT256, when you want a quantum hedge, per Section 10. And keep the deprecation discipline precise: MD5 and CRC are fine as non-security checksums against accidental corruption, and nowhere an adversary can influence the input.&lt;/p&gt;

On Windows the same primitives appear under specific names. The CNG layer exposes hash and MAC providers through BCrypt, detailed in [the CNG architecture guide](/blog/cng-architecture-bcrypt-ncrypt-ksps); Authenticode computes a hash of a portable-executable file (skipping the fields that signing itself modifies) and signs that digest, which is the exact construction Flame subverted, covered in [the Authenticode and catalog-files guide](/blog/authenticode-and-catalog-files-the-crypto-foundation-under-w); and SChannel, the Windows TLS stack, hashes handshake transcripts and has spent two decades retiring SHA-1 across cipher suites, told in [the SChannel algorithm-agility story](/blog/rotating-every-cipher-schannel-and-the-twenty-year-algorithm). The algorithm choices in this guide map onto those APIs directly.
&lt;p&gt;One operational detail sinks more code than any exotic attack: comparing digests or tags with an ordinary equality check. A loop that returns the moment two bytes differ leaks, through its timing, how many leading bytes matched, which is enough for an attacker to recover a secret tag byte by byte. The fix is a constant-time comparison that always scans the whole buffer. This adjacency between hashing and timing side channels is the same family of bug explored in &lt;a href=&quot;https://paragmali.com/blog/they-read-your-plaintext-without-breaking-your-cipher-a-fiel&quot; rel=&quot;noopener&quot;&gt;the padding-oracle field guide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;{`
// Comparing a secret tag with early-exit leaks how many bytes matched.
function naiveEqual(a, b) {
  if (a.length !== b.length) return false;
  for (let i = 0; i &amp;lt; a.length; i++) {
    if (a[i] !== b[i]) return false;      // returns as soon as bytes differ
  }
  return true;
}&lt;/p&gt;
&lt;p&gt;// Constant-time: always scan the whole array, OR the differences together.
function constantTimeEqual(a, b) {
  if (a.length !== b.length) return false;
  let diff = 0;
  for (let i = 0; i &amp;lt; a.length; i++) {
    diff |= a[i] ^ b[i];                   // no branch on the secret bytes
  }
  return diff === 0;
}&lt;/p&gt;
&lt;p&gt;const tag   = [0x9f, 0x1c, 0x00, 0x42, 0xab];
const guess = [0x9f, 0x1c, 0xff, 0x00, 0x00];
console.log(&quot;naive:&quot;, naiveEqual(tag, guess));
console.log(&quot;constant-time:&quot;, constantTimeEqual(tag, guess));
console.log(&quot;In production call a vetted primitive: crypto.timingSafeEqual, CRYPTO_memcmp, or sodium_memcmp.&quot;);
`}&lt;/p&gt;
&lt;p&gt;Two rules cover most real disasters, and they have nothing to do with picking the &quot;strongest&quot; hash. Never use a bare fast hash for passwords, and never use a bare hash where you meant HMAC. The rest of choosing is about axes that are not strength at all: length-extension behavior, speed, FIPS status, parallelism, and construction diversity. What remains is to clear up the myths that cause the disasters those two rules do not.&lt;/p&gt;
&lt;h2&gt;12. Misconceptions and Real-Code Smells&lt;/h2&gt;
&lt;p&gt;The field&apos;s folklore is mostly half-right, which is worse than fully wrong, because half-right beliefs survive code review. Here are the questions that actually decide those reviews.&lt;/p&gt;


No, and this is the single most common misconception in the subject. FIPS 202 says its SHA-3 functions supplement the SHA-1 and SHA-2 families rather than replacing them [@fips-202], and NIST&apos;s Policy on Hash Functions states plainly that there is &quot;no need to transition applications from SHA-2 to SHA-3&quot; [@nist-policy-hash-functions]. SHA-2 and SHA-3 coexist deliberately, on a diversification axis, so the internet&apos;s trust machinery does not rest on one construction. The supersession ladder ran MD5 to SHA-1 to SHA-2 and ended there.


Yes. Full-width SHA-256 and SHA-512 are length-extension-vulnerable, because their digest is the whole final chaining state. So is SHA-224, despite being truncated: it hides only 32 bits of state, which an attacker recovers in about $2^{32}$ work before extending normally [@rfc-3874]. The genuinely immune options are SHA-384, SHA-512/224, SHA-512/256, the SHA-3 family and SHAKE, HMAC, KMAC, and the BLAKE hashes. If you need `H(secret || message)` behavior, use HMAC or one of those instead.


No. Every collision attack on SHA-1 and MD5 attacks collision resistance, and HMAC does not rely on collision resistance. RFC 2104 states directly that MD5&apos;s weaknesses do not compromise its use within HMAC [@rfc-2104]. HMAC-SHA-1 and HMAC-MD5 remain unbroken, though new systems should still prefer HMAC-SHA-256 for margin.


Only as a non-security checksum guarding against accidental corruption, where no adversary can influence the input. The moment an attacker can choose inputs, MD5 collisions become forged certificates, as the 2008 rogue certificate authority and 2012 Flame both showed [@rogue-ca, @stevens-counter-cryptanalysis-crypto13]. Never use MD5 for signatures, certificates, or deduplication of adversarial data.


No. Grover&apos;s algorithm halves the preimage exponent, leaving SHA-256 with about 128-bit preimage resistance, still infeasible [@grover-1996]. For collisions the quantum speedup is marginal once you charge for quantum memory, so SHA-256 keeps roughly 128-bit collision resistance in practice [@bernstein-sharcs09]. The hedge, if you want more margin, is a longer output such as SHA-384 or SHA-512, not a new construction.


SHA-256 for general integrity, signatures, and interoperability, especially where FIPS validation matters [@fips-180-4]. BLAKE3 when you want maximum throughput, streaming, or a KDF and do not need FIPS [@blake3-repo]. SHA-512/256 when you want length-extension immunity plus FIPS on 64-bit software.


No. Both are built to be fast, which is exactly what you do not want for passwords, where speed helps the attacker guess. Use a purpose-built slow function: Argon2id for new systems, or scrypt, bcrypt, or PBKDF2. BLAKE3&apos;s own README says the same and points to Argon2 [@blake3-repo].

&lt;p&gt;The misuse catalog is the FAQ&apos;s mirror image: the same mistakes, seen from the code side.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;H(secret || message)&lt;/code&gt; pressed into service as a MAC (use HMAC or KMAC). Passwords fed to a bare or unsalted fast hash (use Argon2id). Truncating a fixed digest to an odd length instead of asking an XOF (use SHAKE or a BLAKE3 XOF). Comparing tags with &lt;code&gt;==&lt;/code&gt; or an early-exit loop instead of a constant-time check.These last two, ad hoc truncation and non-constant-time comparison, are the ones that pass functional tests perfectly and fail only under an adversary, which is why they survive so long in production. Rolling your own Merkle tree without domain-separating leaf and internal nodes. Treating a hash as if it provided encryption. And assuming a real hash is a perfect random oracle rather than an approximation of one.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Return, finally, to the two files from the opening, the ones that shared the SHA-1 digest &lt;code&gt;38762cf7f55934b34d179ae6a4c80cadccbb7f0a&lt;/code&gt; [@shattered]. You can now read that string precisely. It is not evidence that hashing is broken, or that longer is always safer, or that SHA-3 rode in to replace the fallen. It is a single clause, collision resistance, failing on a single aging construction, and being weaponized because signatures sign the digest, not the file. The answer the field actually gave was not one replacement but two moves at once: widen the margins of the survivor, SHA-2, and diversify into unrelated constructions, the SHA-3 sponge and the BLAKE3 tree, so no future break can take everything down together. A cryptographic hash makes one promise. Mastery is knowing exactly which clause of that promise your protocol leans on, and choosing the function and the mode that keeps it.&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;cryptographic-hash-functions-field-guide&quot; keyTerms={[
  { term: &quot;Collision resistance&quot;, definition: &quot;Infeasibility of finding any two distinct inputs with the same digest; generic cost about 2^(n/2) by the birthday bound.&quot; },
  { term: &quot;Length extension&quot;, definition: &quot;Computing the hash of m followed by padding and a chosen suffix from the digest of m and its length, without knowing m; afflicts full-width Merkle-Damgard hashes and SHA-224.&quot; },
  { term: &quot;Merkle-Damgard&quot;, definition: &quot;Iterated hash that folds padded message blocks through a compression function; the digest is the final chaining state.&quot; },
  { term: &quot;Sponge&quot;, definition: &quot;The Keccak and SHA-3 construction with a hidden capacity, which makes it length-extension-immune and a native extendable-output function.&quot; },
  { term: &quot;XOF&quot;, definition: &quot;Extendable-output function that emits output of any requested length, such as SHAKE128 and SHAKE256.&quot; },
  { term: &quot;HMAC&quot;, definition: &quot;Nested keyed message authentication code that authenticates messages without relying on the hash&apos;s collision resistance.&quot; }
]} questions={[
  { q: &quot;Why does a 256-bit hash provide only 128-bit collision resistance?&quot;, a: &quot;By the birthday bound, a repeat appears after only about 2^(n/2) draws in a space of 2^n values.&quot; },
  { q: &quot;Did SHA-3 replace SHA-2?&quot;, a: &quot;No. FIPS 202 states SHA-3 supplements the SHA-2 family, and NIST&apos;s policy says there is no need to transition; they coexist for construction diversity.&quot; },
  { q: &quot;Which SHA-2 variants resist length extension, and why?&quot;, a: &quot;SHA-384, SHA-512/224, and SHA-512/256, because they hide at least 128 bits of the final state; SHA-224 does not, hiding only 32 bits.&quot; },
  { q: &quot;Is HMAC-SHA-1 broken by the SHA-1 collision attacks?&quot;, a: &quot;No. HMAC does not depend on collision resistance, so HMAC-SHA-1 and HMAC-MD5 remain unbroken.&quot; },
  { q: &quot;What is the correct way to hash a password?&quot;, a: &quot;A purpose-built slow function such as Argon2id, scrypt, bcrypt, or PBKDF2, never a bare fast hash.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>cryptography</category><category>hash-functions</category><category>sha-2</category><category>sha-3</category><category>blake3</category><category>collision-resistance</category><category>length-extension</category><category>applied-cryptography</category><author>noreply@paragmali.com (Parag Mali)</author></item></channel></rss>