Skip to content
Crypto2026-09-13Shuai Li9 min read

What is a Hash Collision? MD5 and SHA-256 Security Deep Dive

When you download an installer, the publisher usually ships a hash alongside it. You hash the local file, compare, and treat a match as “intact.” That only works if two different files almost never share a digest — and “almost never” depends on the algorithm. MD5 collisions are seconds on a laptop; SHA-1 fell in 2017 and chosen-prefix got cheaper with Shambles (2020); SHA-256 still has no public collision. This article covers the pigeonhole principle, birthday attacks, real incidents, and why a broken bare hash is not the same story as HMAC. Follow along with the MD5 hash generator or SHA-256 hash generator; to compare against a published digest use the Hash Verifier.

What Is a Hash Collision

A hash function compresses arbitrary-length input into a fixed-length output. MD5 always emits 128 bits; SHA-256 always emits 256. Infinite input space, finite output space — by the pigeonhole principle, collisions must exist.

A collision: two distinct inputs, same hash.

hash("fileA") = 9e107d9c...
hash("fileB") = 9e107d9c...   ← same hash, but fileA ≠ fileB

Existence is not the scare. Cost to find one is. If a search needs on the order of 2^128 operations, public compute cannot finish it in any meaningful time.

Cryptographers also separate three problems:

ProblemAttacker goalIdeal N-bit cost
CollisionAny two distinct inputs, same hash~2^(N/2) (birthday bound)
Second preimageGiven m, find m'≠m with same hash~2^N
PreimageGiven a digest, find any input~2^N

Download checks and certificate signatures fear collisions and second preimages. “MD5 decrypt” searches are really preimage / rainbow-table problems — see MD5 “decrypt” and collisions.

Birthday Paradox and Birthday Attacks

Intuition says a 128-bit space means collision probability 2^-128. That ignores many pairwise comparisons.

Classic birthday paradox: in a room of 23 people, the chance two share a birthday crosses 50% — far fewer than 365/2 — because pair counts grow quadratically.

For a hash with output space size N (MD5: N=2^128), after about n random samples the chance of at least one collision is roughly:

P ≈ 1 − exp( − n² / (2N) )

For P≈50%, n ≈ 1.2 √N — the birthday bound: about 2^(N/2) hashes, not 2^N.

  • 128-bit (MD5): ~2^64
  • 160-bit (SHA-1): ~2^80
  • 256-bit (SHA-256): ~2^128

So SHA-256 offers 128-bit collision resistance by the birthday bound, not 256-bit; 256-bit is the preimage scale.

Birthday search is only a generic lower bound. Structured differential attacks beat 2^(N/2) — that is how MD5 and SHA-1 actually fell.

Identical-prefix vs chosen-prefix

  1. Identical-prefix: both files share a prefix; the attacker inserts crafted differential blocks afterward. The SHAttered PDFs are this class.
  2. Chosen-prefix: the attacker picks different meaningful prefixes (legit vs malicious), then appends colliding suffixes. Rogue CA (2008), Flame (2012), and SHA-1 Shambles (2020) weaponize this.

If you still verify downloads with MD5, an attacker need not match the exact official package — they can build a malicious file that shares a hash with some other plausible artifact and then poison the hash channel you trust.

MD5: From Broken to Routine

YearEvent
2004Xiaoyun Wang’s team publishes practical MD5 collisions
2007Chosen-prefix collisions demonstrated
2008Rogue CA certificate via MD5 collision
2012Flame forges a Microsoft code-signing cert with MD5 collision
Mid-2010s–nowIdentical-prefix pairs in seconds on ordinary CPUs

In 2008, two different certificates shared an MD5; the CA signed the “benign” one and the signature validated the malicious twin.

Status in 2026: do not use MD5 wherever a digest must resist forgery. Non-adversarial uses (dedupe, cache keys, change detection inside a system you control) remain fine. Not for downloads under attack, certificates, passwords, or API authenticity. Boundaries: MD5 guide.

SHA-1: SHAttered and Shambles

Ideal birthday bound ~2^80; reality was worse.

  • SHAttered (2017, Google + CWI): two different PDFs, same SHA-1; roughly 6,500 CPU-years + 110 GPU-years, on the order of $110k. Browsers and CAs dropped SHA-1 signatures.
  • Shambles (2020): chosen-prefix cost entered the budget of well-funded attackers; Git and similar content-addressed systems accelerated SHA-256 migration.
shattered-1.pdf  →  38762cf7f55934b34d179ae6a4c80cadccbb7f0a
shattered-2.pdf  →  38762cf7f55934b34d179ae6a4c80cadccbb7f0a

Status in 2026: no new design should use bare SHA-1 for integrity or signature digests. Legacy git objects and old payment APIs may still demand it — that is compatibility, not a security endorsement. The on-site SHA-1 tool is positioned for those leftovers.

SHA-256: No Public Collision

SHA-256’s birthday-bound collision resistance is 2^128. As of 2026, no public SHA-256 collision exists.

Brute-force search is far beyond plausible global compute. Collisions exist in theory; finding one does not. On the quantum side, Grover mainly hits preimage cost — see Do hashes fear quantum computing?.

Deeper comparison: SHA-256 guide, SHA-256 vs MD5.

HMAC Context: Broken Hash ≠ Instant Broken MAC

HMAC is a keyed hash:

HMAC(K, m) = H( (K' ⊕ opad) ‖ H( (K' ⊕ ipad) ‖ m ) )

It answers a different question: with a shared secret, prove the message was not altered and came from a key holder. Anyone can recompute a bare download hash; not an HMAC.

Engineering points tied to collisions:

  1. Different threat model. Public MD5/SHA-1 collision attacks target unkeyed digests. Forging HMAC usually needs the key (or a related-key break). “I can collide MD5” ≠ “I can forge HMAC-MD5.”
  2. Length extension ≠ collision. Merkle–Damgård bare hashes (MD5/SHA-1/SHA-256) allow length-extension tricks; HMAC’s nested padding blocks that class of misuse. Need a MAC? Use HMAC — do not hand-roll H(key ‖ message).
  3. Still migrate. HMAC-MD5 / HMAC-SHA1 lack “seconds on a laptop” public breaks like bare collisions, but standards already retired them. New work: HMAC-SHA256 (or stronger). See the HMAC generator and HMAC guide.
  4. Do not swap tools. Webhooks/API signatures → HMAC. ISO/installer integrity → published SHA-256 plus (better) a signature. The Hash Verifier compares digests; it is not a keyed API verification bench.

Collisions kill trust in “digest as anti-forgery fingerprint.” HMAC adds a key. Lose the key and both stories fail; keep the key and you should still move the underlying hash to the SHA-256 family.

Python Demo: Concept and File Checks

MD5 here is only the API demo — you will not randomly collide on a laptop:

import hashlib

def md5_hex(s: str) -> str:
    return hashlib.md5(s.encode()).hexdigest()

a, b = "hello", "world"
print(md5_hex(a))  # 5d41402abc4b2a76b9719d911017c592
print(md5_hex(b))  # 7d793037a0760186574b0282f2f435e7

def verify_collision(x: str, y: str) -> bool:
    if x == y:
        return False
    return md5_hex(x) == md5_hex(y)

# Real pairs are differentially constructed bytes, not random strings.
# Search for published MD5 collision examples (e.g. Marc Stevens) to verify.

Production file checks usually stream SHA-256:

import hashlib

def file_sha256(path: str) -> str:
    h = hashlib.sha256()
    with open(path, "rb") as f:
        for chunk in iter(lambda: f.read(8192), b""):
            h.update(chunk)
    return h.hexdigest()

expected = "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
actual = file_sha256("./download.bin")
print("OK" if actual == expected else "file corrupted or tampered")

In the browser: drop the file into the Hash Verifier, pick SHA-256, paste the publisher’s expected digest.

Real-World Consequences

File integrity: MD5-checked downloads can be swapped for a colliding malicious installer.

Code signing: CAs and notarization depend on hashes; SHA-1 left the default path once collisions were affordable.

Git objects: historically SHA-1; post-SHAttered/Shambles the migration path is SHA-256.

Blockchains: ecosystems that bet on SHA-256 collision resistance stay on long digests for a reason.

Choosing by Scenario

ScenarioChooseWhy
File integritySHA-256 (or stronger)MD5/SHA-1 collisions are practical
Password storagebcrypt / Argon2Fast hashes favor brute force
Signature digestsSHA-256 or SHA-3Default in major CAs and libraries
Message auth (API/webhook)HMAC-SHA256Shared key + length-extension resistance
Non-security dedupe / cache keysMD5 or xxHashSpeed when forgery is out of scope
Content-addressed storageSHA-256SHA-1 is no longer a trust root

Password trap: SHA-256 is too fast — use bcrypt. Division of labor: Hashing vs encryption.

Computing and Verifying with ToolVault

All of these run locally in the browser:

Step-by-step: How to verify a hash.

FAQ

What is the probability of a SHA-256 collision?

Random search sits near 2^128 (birthday bound) — beyond practical attackers. Theoretical collisions exist; constructing one is the hard part.

Is MD5 still OK for anything?

Yes for non-security uses: cache keys, dedupe, quick fingerprints without an adversary forging matches. Never for certificates, passwords, or adversarial download integrity.

MD5 vs SHA-256 for file downloads?

Ship and verify SHA-256 (or stronger). Chosen-prefix MD5 collisions can forge “hash matches, content differs.”

Is HMAC-MD5 also completely dead?

Unlike bare MD5, public collision recipes do not directly forge HMAC without the key. New designs still have no reason to keep HMAC-MD5/SHA1 — move to HMAC-SHA256. Use the HMAC generator for legacy checks.

How do I verify a published hash quickly?

Paste file/text plus the expected digest into the Hash Verifier, or compute with the SHA-256 Hash Generator. Both stay local.

Summary

Collisions are about cost, not existence. MD5 is cheap to abuse; SHA-1 left the secure default after SHAttered/Shambles; SHA-256’s collision cost remains ~2^128. Use SHA-256+ for integrity and signature digests, HMAC-SHA256 for API authenticity, and keep MD5 for dedupe/caching where forgery resistance is not required.


Provided by ToolVault. Related tools: MD5 Hash Generator, SHA-256 Hash Generator, Hash Verifier, HMAC Generator. Related reading: MD5 hash guide, MD5 “decrypt” and collisions, SHA-256 hash guide, HMAC guide, Hashing vs encryption, Do hashes fear quantum computing?. See the homepage for more developer tools.

Implementer's note

When we ported hash tools to the browser, SubtleCrypto SHA-256 ran roughly 8–15× a pure JS path — 100MB inputs dropped from minutes to seconds. Vendors keep MD5 out of SubtleCrypto on purpose (no official fast path for a retired digest), so MD5 goes through SparkMD5 while SHA family uses crypto.subtle.digest. The Hash Verifier runs one selected algorithm at a time (not five digests in parallel), normalizes case and trim before compare, and surfaces a collision warning when MD5 or SHA-1 is selected so “Match” is not misread as “safe under attack.”