In this article
- TL;DR
- What "SHA-256 was broken" actually means
- How Merkle-Damgård works
- How length-extension works
- Reproducing the attack with hash_extender
- Why SHA256d immunises Bitcoin against length-extension
- HMAC, the fix for everyone else
- Why Bitcoin stayed on SHA-256, not SHA-3
- Quantum, Grover, and SHA-256
- Where SHA-256 fails on passwords
- Where SHA-256 lives inside Bitcoin
- The 2026 verdict, by use case
- Further reading
- Disclaimer
TL;DR
A working attack on SHA-256 exists. I reproduced it on a throwaway VM in under ten minutes. It does not touch Bitcoin. The attack is length-extension against the Merkle-Damgård construction, and Bitcoin's double-SHA256 was published as the defence six years before the genesis block. Outside Bitcoin the canonical fix is HMAC (RFC 2104). Grover's algorithm cuts SHA-256 from 2²⁵⁶ to 2¹²⁸, which is still effectively infinite.
What "SHA-256 was broken" actually means
Every few months a fresh headline declares that SHA-256 has been broken. The forums spike. A Reddit thread in r/cryptography (thread 15jpuzg) and a long Hacker News discussion (item 36058754) both circle the same misunderstanding. There is a specific attack against SHA-256 in a specific context, and the rest of the internet flattens it into "Bitcoin is in danger."
It is not. I work in the crypto self-custody space, and every time this headline cycles, someone forwards me the thread asking whether their cold storage is at risk. Their cold storage is not at risk. Their assumption about how SHA-256 is used everywhere else on the internet is the part that should worry them.
The attack is called a length-extension attack. It is real. It is reproducible in under ten minutes on a laptop. Bitcoin defeats it by design. Every other "SHA-256 broken" claim in 2026 either reduces to length-extension (which Bitcoin handles), to partial-round academic cryptanalysis (which has not produced a practical exploit on full SHA-256), or to a misuse of SHA-256 in password storage, which is a design failure rather than an algorithm failure.
The walk-through below shows what length-extension actually does, why Bitcoin's SHA256d construction makes it impossible against Bitcoin's hash chain, what the canonical mitigation looks like in non-Bitcoin code (HMAC), and the one use case where SHA-256 genuinely is insecure: password storage. At the end you reproduce the attack against a deliberately-vulnerable demo server with a Python tool, then watch the same attack fail when the server switches to Bitcoin's construction.
How Merkle-Damgård works
SHA-256 is a member of the SHA-2 family, all of which share the same general design called the Merkle-Damgård construction. Understanding it takes about a minute, and that minute is what makes length-extension obvious.
A Merkle-Damgård hash takes a long message and chops it into fixed-size blocks (64 bytes for SHA-256). It starts with a fixed initial state (the IV), then runs a compression function on each block that mixes the block into the state. After the final block, the algorithm outputs the state directly as the hash digest.
That last sentence is the whole problem. The final digest of the hash is the internal state at the end of the computation. If you know Hash(message), you know the internal state of the compression function after it processed message. You can resume from there.
That is what length-extension exploits. Given Hash(secret || message), you hold the state the compression function arrived at after consuming secret || message. You resume the computation from that state, append any extra data you want, and produce a valid hash. You never learn secret.
SHA-3 (Keccak) does not work this way. Its sponge construction only outputs a truncation of the internal state, not the state itself. SHA-512/256, BLAKE2, and BLAKE3 use similar truncation tricks. Those algorithms are immune to length-extension by design. SHA-256, the algorithm Bitcoin runs on, is not.
This is the structural fact behind every "SHA-256 is broken" headline. Now the attack itself in code.
How length-extension works
The canonical motivating example, used in the Wikipedia entry on length-extension attacks and reproduced in every crypto textbook since 2009, goes like this.
A web server signs API requests by computing SHA-256(secret || params). It publishes the signature alongside the request:
GET /api?user=alice&role=user&sig=a3f1...
The server validates by recomputing SHA-256(secret || "user=alice&role=user") and checking against sig. The construction looks fine to anyone who has not stared at Merkle-Damgård padding rules, which is most developers shipping code in 2026.
The attacker captures one valid (params, sig) pair. They guess the byte-length of secret (typically 16, 32, or 64, so they sweep all three). They compute the Merkle-Damgård padding bytes that SHA-256 would have appended to secret || params before the final compression step. The padding is deterministic (RFC 6234 §4.1). Then they initialise a fresh SHA-256 state from the captured sig, because the captured signature IS the internal state of the compression function after consuming secret || params || (auto-padding). From that state they continue the SHA-256 computation, feeding in &role=admin or any chosen extension, and emit the new state as the forged signature.
The attacker sends:
GET /api?user=alice&role=user[padding bytes]&role=admin&sig=<forged>
The server recomputes SHA-256(secret || "user=alice&role=user[padding]&role=admin") and arrives at exactly the forged signature, because the construction commutes with the attacker's extension. The attacker is now admin.
The most famous public exploit of this pattern is the 2009 Flickr API forgery by Thai Duong and Juliano Rizzo, where the same construction allowed unauthorised photo deletion across the Flickr API. The technique is older (Daniel Bleichenbacher discussed it in the 1990s) but the Flickr case made it a fixture of penetration-test syllabi.
You need one valid (params, sig) pair and the byte-length of the secret. That is the entire attack surface. SHA-256 is not broken in any algorithmic sense. The developer just used the wrong construction.
Reproducing the attack with hash_extender
You can reproduce the attack on your own machine in under ten minutes. The full step-by-step walkthrough is in the HowTo structured-data block at the top of this page. The summary version, with primary-source repositories.
The Python attack tool eid3t1c/Hash_Extender automates the length-extension forgery for MD5, SHA-1, SHA-256, and SHA-512. The earlier canonical C implementation by iagox86/hash_extender (the original 2014 release) does the same job and is the tool cited in most length-extension tutorials since 2014. Either works.
Pair it with magodo/sha256-length-extension-attack-demo, a deliberately-vulnerable Flask server that signs query strings with SHA-256(secret || params). Run the server, capture a token, run hash_extender, submit the forgery. The server accepts it. You are now admin on a webserver whose secret you never learned.
Then change one line of the demo server. Replace SHA-256(secret || params) with SHA-256(SHA-256(secret || params)) and re-run the attack. The forgery fails. The second hash takes the full 256-bit output as input, and the attacker has no internal state to extend from. That single edit reproduces what Bitcoin does on every block hash, every TXID, every Merkle root.
A Rust reference implementation of the same attack is in Sylvain Kerkour's 2026 write-up, useful if you want to follow the byte-level state-recovery logic in a typed language. For the simplest reproduction the Python tools above are faster.
I ran this end-to-end the first time I worked on the post. Watching the forgery succeed and then watching it die against SHA-256(SHA-256(...)) is more convincing than any explanation of Merkle-Damgård on the page. If you want cryptographic intuition rather than cryptographic vocabulary, this is the cheapest attack you can run.
Why SHA256d immunises Bitcoin against length-extension
Bitcoin computes SHA-256(SHA-256(x)), called SHA256d, for every place a hash appears in the consensus-critical protocol. Block headers feeding mining proof-of-work. Transaction IDs. Merkle roots that aggregate transactions inside a block. The block hash miners search for, a SHA256d that has to come in below the difficulty target.
Ferguson and Schneier proposed the double-hash construction in Practical Cryptography (2003) as the canonical defence against length-extension attacks on SHA-2. The argument is short. The outer SHA-256 is computed over the full 256-bit output of the inner SHA-256. An attacker who knows SHA256d(secret || params) does not know the internal state of the outer compression function in any usable way. To recover that state, they would have to invert the outer SHA-256, which is a preimage attack at roughly 2²⁵⁶ operations. That is the security guarantee.
A widely-cited crypto.stackexchange.com answer traces the rationale through Tahoe-LAFS (which adopted SHA256d in 2006) to Bitcoin's adoption in 2009. The whitepaper just says "SHA-256" and the cryptography mailing list is silent on the construction choice, so we cannot prove Satoshi explicitly chose SHA256d to defeat length-extension. We do know that Ferguson-Schneier had published the construction six years earlier, that Tahoe-LAFS was already using it for filesystem-capability hashes on that exact rationale, and that Bitcoin shipped with SHA256d on day one. Draw your own conclusion. The technical fact stands either way: Bitcoin's hash chain is immune to length-extension, and the attack producing "SHA-256 is broken" headlines does not apply to any layer of the Bitcoin protocol.
HMAC, the fix for everyone else
Most software developers will never write SHA256d. They will write HMAC.
HMAC (RFC 2104) is the universal length-extension-immune wrapper for any Merkle-Damgård hash. Given a hash function H (SHA-256, SHA-1, MD5, HMAC works for all of them), HMAC is defined as:
HMAC(key, message) = H( (key ⊕ opad) || H( (key ⊕ ipad) || message ) )
opad and ipad are fixed byte patterns (0x5c5c5c... and 0x363636...). The inner hash absorbs the message. The outer hash hashes the inner output with a different key derivative.
The construction looks similar to SHA256d but is more flexible. HMAC takes a key as a first-class parameter, supports any underlying hash, and integrates cleanly with key-derivation function stacks. It has been the IETF standard since RFC 2104 shipped in 1997, and every cryptographic library treats HMAC-SHA256 as a primitive.
The two places you most often hit it in production are TLS 1.3, which uses HMAC-SHA256 inside its HKDF key-schedule (RFC 8446 §7.1), and JWT tokens with the HS256 algorithm, which are signed HMAC-SHA256(secret, header.payload). AWS SigV4 and WebAuthn both pull on the same primitive for the same reason.
If your code computes hash(secret + message) anywhere outside Bitcoin, replace it with HMAC. The cost is one extra hash invocation. The security gain is total immunity to length-extension.
Why Bitcoin stayed on SHA-256, not SHA-3
SHA-3 (Keccak), standardised by NIST in 2015 (FIPS-202), is built on a fundamentally different design called the sponge construction, which is length-extension-immune by construction. No double-hash needed. No HMAC wrapper needed. SHA-3 hashes can be used as MACs directly (sometimes called KMAC) and remain secure.
Bitcoin still runs on SHA-256 in 2026 for reasons that are mostly path-dependence rather than cryptographic. Switching the hash algorithm requires a hard fork. Every full node, every miner, every wallet, every block-explorer, every BIP, every signature scheme touches SHA-256 somewhere. A coordinated migration is technically possible but politically catastrophic. Tens of billions of dollars of ASIC hardware exists specifically to compute SHA-256 at maximum throughput, and replacing the algorithm obsoletes the entire mining base overnight. SHA-256 is also faster than SHA-3 on modern CPUs and dramatically faster on ASICs, which matters for verification on every full node.
The cryptographic argument for staying put is simpler. SHA256d already solves the only structural weakness of SHA-256 that matters in Bitcoin's threat model. There is no live problem migration would fix. SHA-3 would have been a defensible choice in 2009. The cost of migration in 2026 dwarfs the benefit.
Quantum, Grover, and SHA-256
Quantum computers do not break SHA-256.
The relevant quantum algorithm against a hash function is Grover's algorithm, which gives a quadratic speed-up on unstructured search. For SHA-256 this reduces preimage resistance from 2²⁵⁶ classical operations to 2¹²⁸ quantum operations. 2¹²⁸ is still effectively infinite, far beyond any plausible quantum hardware projected for the next several decades.
Shor's algorithm is the one to actually fear, and it does not touch SHA-256. Shor gives an exponential speed-up on the discrete logarithm problem, which breaks ECDSA (Bitcoin's signature scheme) in polynomial time on a sufficiently large quantum computer. Bitcoin's quantum risk lives in the signatures, not in the hash.
The current 2026 quantum picture for Bitcoin specifically, including BIP-360, BIP-361, and the PACTs migration framework, is the subject of two separate posts on this site. See BIP-360/361: Quantum-Resistant Bitcoin and Quantum Computing, Bitcoin, and Google's 2026 Announcement. The short version. SHA-256 is fine. ECDSA needs migration. The timelines for both are decades apart.
The harvest-now-decrypt-later threat applies to Bitcoin's ECDSA signatures only. It does not apply to SHA-256 in any meaningful way, because a 2¹²⁸-strong primitive is unrecoverable harvest-or-not.
Where SHA-256 fails on passwords
The one context where "SHA-256 is insecure" is fair is password storage.
This has nothing to do with length-extension. SHA-256 is too fast. A modern consumer GPU computes billions of SHA-256 hashes per second, and Hashcat publishes the benchmarks openly. For an unsalted SHA-256-hashed password under about 15 random characters, an attacker with one consumer GPU brute-forces the entire space in hours.
Password storage requires a hash function that is deliberately slow and memory-hard, so that a GPU has no advantage over a CPU. Use Argon2id (RFC 9106, OWASP-recommended 2026), or scrypt or bcrypt if you are stuck with an older stack.
If you find SHA-256 used for password storage in 2026 code, the fix is to migrate the entire user base (typically by re-hashing on next login). Do not add length-extension defences. The real problem is brute-force speed, and length-extension is unrelated to that.
Where SHA-256 lives inside Bitcoin
For Bitcoin specifically, SHA-256 (almost always as SHA256d) appears in several distinct roles:
| Role | What it does |
|---|---|
| Mining proof-of-work | Miners search for a nonce such that SHA256d(blockheader) is below the target |
| Transaction IDs | TXIDs are SHA256d of the transaction |
| Merkle root | Aggregates all TXIDs in a block |
| Block hash | SHA256d of the block header |
| P2PKH address | RIPEMD160(SHA-256(pubkey)) then base58check encoding |
| BIP-39 derivation | SHA-256 used inside PBKDF2-HMAC-SHA512 for seed-to-key derivation |
Each of these would be a catastrophic loss of integrity if SHA-256 broke. None of them are at practical risk in 2026. The known practical attacks (length-extension, partial-round collisions on 31-of-64 rounds, fast GPU brute force on small input spaces) do not reach the full SHA-256 algorithm in any role that matters in Bitcoin.
The relevant comparison is SHA-1, which was broken in practice by Google's 2017 SHAttered collision attack against full SHA-1. SHA-256 is not in that state and has no near-term cryptanalytic trajectory toward it.
The 2026 verdict, by use case
The chain holds. Every consensus-critical use of SHA-256 in Bitcoin runs through SHA256d, which I have already shown is immune to length-extension. There is no practical preimage attack on full SHA-256 in 2026, no practical collision attack, and nothing on the cryptanalytic horizon that gets close. Bitcoin mining, TXIDs, Merkle roots, P2PKH and P2WPKH addresses, BIP-39 seed derivation through PBKDF2-HMAC-SHA512: all secure.
Outside Bitcoin, anywhere SHA-256 sits behind an HMAC wrapper (TLS 1.3 record signing, JWT-HS256, AWS SigV4) it is also secure. Raw SHA-256 used for content addressing or as a pre-hash for digital signatures or long-term archive integrity checks is fine, because length-extension is irrelevant when there is no secret and no MAC.
Two patterns still fail in 2026 and you should fix them on sight. Home-grown MACs in the shape Hash(secret || message) get trivially forged by length-extension. Switch to HMAC. Raw SHA-256 password storage, salted or not, gets brute-forced by a single GPU because SHA-256 is too fast. Switch to Argon2id.
Both failures are construction failures, not algorithm failures. SHA-256 itself is still doing the job it has been doing since 2001.
Further reading
This article is part of a small cluster on btc2h.com that examines the cryptographic primitives Bitcoin actually depends on, and what current research means for each of them. Three companion reads:
- BIP-360 / BIP-361: The Quantum-Resistant Bitcoin Migration Plan covers the signature-side quantum picture, where the real long-term risk lives.
- Quantum Computing, Bitcoin, and Google's 2026 Announcement puts the 2026 quantum-hardware news cycle in context.
- btcrecover tutorial 2026 shows why SHA-256's GPU-brute-force speed is the right answer for wallet-password recovery and the wrong answer for password storage.
Primary-source bibliography for this article (verified accessible 2026-05-12 unless noted):
- Wikipedia, Length extension attack
- Wikipedia, SHA-2
- RFC 6234, US Secure Hash Algorithms (SHA-256 padding spec)
- RFC 2104, HMAC Keyed-Hashing for Message Authentication
- crypto.stackexchange.com Q779, Why does Bitcoin use double SHA-256?
- Reddit r/cryptography, SHA-256 length extension thread
- Hacker News thread 36058754
- arXiv 2406.20072, partial-round SHA-256 cryptanalysis (claim: partial-round results, no practical full-round attack. Verify against the paper's abstract before quoting numerical bounds.)
- Kerkour, Breaking SHA-2 length extension attacks in practice with Rust
- eid3t1c/Hash_Extender (Python attack tool)
- magodo/sha256-length-extension-attack-demo (vulnerable Flask server)
- sjlombardo length-extension gist (2012)
- Ferguson & Schneier, Practical Cryptography (2003), the canonical SHA256d publication
Disclaimer
This article is educational content for Bitcoin holders and developers. It is not legal, financial, or cryptographic-engineering advice. Real-world cryptographic deployments require formal review by qualified specialists. Do not implement security-critical code from a blog post. For production systems handling secrets, use battle-tested libraries (libsodium, OpenSSL, Bouncy Castle) rather than rolling your own primitives. For legal or compliance questions about cryptographic agility under FINMA, GDPR, or NIS2, consult qualified counsel.