francescomargiotta.com
  • Security
  • Backend

MD5, SHA-1, SHA-256: what "broken" actually means

Collisions, preimages, the avalanche effect. Why MD5 is unusable for signatures yet legitimate for cache keys, and why SHA-256 is the wrong choice for passwords.

by Francesco Margiotta Casaluci6 min read

MD5 is "broken", SHA-1 is "broken", use SHA-256. That summary is everywhere, and it is too coarse to be useful: it does not say in what sense they are broken, it does not say for which uses they actually are, and above all it leads to the wrong conclusion that SHA-256 is the right answer to every question. It is not: for passwords, SHA-256 is as poor a choice as MD5.

It is worth separating the properties a hash function can have, because "broken" means different things depending on which property fell.

What a hash function does

A cryptographic hash function takes an input of any length and produces a fixed-length output. It must be deterministic — same input, same output, always — and fast to compute forwards.

input: "ciao"

MD5      (128 bit)  6e6bc4e49dd477ebc98ef4046c067b5f
SHA-1    (160 bit)  1e4e888ac66f8dd41e00c5a7ac36a32a9950d271
SHA-256  (256 bit)  b133a0c0e9bee3be20163d2ad31d6248db292aa6dcb1ee087a2aa50e0fc75ae2

The most visible property is the avalanche effect: a minimal change in the input must make the output completely different, with no residual similarity.

SHA-256("ciao")  b133a0c0e9bee3be20163d2ad31d6248db292aa6dcb1ee087a2aa50e0fc75ae2
SHA-256("Ciao")  25c73520e69f4bf229811e8e46ffe7d80471544b9bee15ed25044b86be4115ad
One capital letter of difference: 60 of the 64 hex characters change.

The three properties, and which falls first

Here is the distinction that makes everything else readable. There are three security guarantees, of decreasing strength, and they fall in order.

PropertyMeaningIf it falls
Collision resistanceHard to find any two inputs with the same hashDigital signatures and certificates stop being trustworthy
Second-preimage resistanceGiven one input, hard to find another with the same hashA specific file can be swapped for a forged one
Preimage resistanceGiven a hash, hard to find any input producing itThe hash stops hiding the input

Collision resistance is the weakest of the three for a statistical reason: the birthday paradox. On an n-bit output it takes roughly 2^(n/2) attempts to find a collision, against the 2^n needed to invert a hash. For MD5 that means 2^64 instead of 2^128 — which is why it is always the first to fall.

Where the algorithms stand

AlgorithmOutputStatusUse
MD5128 bitPractical collisions since 2004, chosen-prefix tooNever for security
SHA-1160 bitPractical collision demonstrated in 2017Never for security
SHA-256256 bitNo known practical attackDefault choice
SHA-512512 bitNo known practical attackFaster than SHA-256 on 64-bit CPUs
SHA-3224–512 bitNo known practical attackDifferent construction, useful as an alternative
BLAKE3variableNo known practical attackVery fast, parallelisable

MD5's collapse is worth stating precisely, because the timeline shows the gap between a theoretical attack and an operational one. The first collisions arrive in 2004. In 2008 a group of researchers uses them to obtain a fraudulent but technically valid certificate authority certificate. In 2012 the Flame malware exploits a chosen-prefix MD5 collision to sign its own components as if they came from Microsoft, spreading through the Windows update channel. Eight years passed between "a collision was found" and "a real attack signed malicious code".

SHA-1 followed the same path: theoretical attacks from 2005, the first concrete collision in 2017 with two different PDFs sharing a digest, and in 2020 the chosen-prefix collision — the one that lets an attacker target existing documents rather than construct two to order.

The worst mistake: fast hashes for passwords

This is where "use SHA-256" becomes actively harmful. General-purpose hash functions are designed to be extremely fast, and speed is exactly the wrong property when the input you are protecting is a password.

If a database is stolen, the attacker does not need to invert the hash: they only need to hash billions of candidate passwords and compare. A consumer-grade GPU tries tens of billions of SHA-256 operations per second. An eight-character random password holds for hours. A human-chosen one, far less.

FunctionAttempts per second (order of magnitude)Suitable for passwords
MD510¹¹No
SHA-25610¹⁰No
bcrypt (cost 12)10⁴Yes
scrypt / Argon2id (sensible parameters)10³–10⁴Yes, preferable

Where MD5 is still legitimate

This part usually gets omitted, but it saves time otherwise spent replacing MD5 where it does no harm. When no adversary can choose the input, MD5 is simply a fast 128-bit hash function.

  • Cache keys and internal deduplication, where you generate the inputs yourself.
  • Verifying transfers against accidental corruption, not against tampering.
  • Partitioning and spreading load across buckets.
  • HTTP ETags, where the function detects a change rather than guaranteeing origin.

The boundary is sharp: if someone stands to gain by handing you a crafted input, MD5 is not acceptable. Everywhere else the choice is about performance, not security. That said, for anything new there is no reason to pick MD5: BLAKE3 is faster and does not oblige you to justify it at every code review.

Authenticated integrity needs HMAC

A recurring mistake is concatenating a secret key with a message and hashing the result, hoping to get an authentication code. With SHA-256 that scheme is vulnerable to a length-extension attack: the Merkle–Damgård construction SHA-256 is built on exposes its internal state in the digest, which lets an attacker continue the computation and produce a valid digest for a longer message without knowing the key.

Vulnerable:  SHA256(key ‖ message)
Correct:     HMAC-SHA256(key, message)

HMAC-SHA256("chiave-segreta", "ciao")
  c9b5740a9e60f9f8cef49b4de3dabc25e5908962e6901a87c4bb9e9955c5d6a9

HMAC applies the hash twice with two distinct key derivations, which neutralises length extension. It is a standard primitive present in every crypto library: there is no reason to improvise an alternative. Worth noting that SHA-3 and BLAKE2/3 are not subject to this attack by construction — but even with those, you authenticate a message using the primitive designed for it.

Summary

  • File integrity and digital signatures: SHA-256, or BLAKE3 where speed matters.
  • Passwords: Argon2id, otherwise scrypt or bcrypt. Never a general-purpose hash, however modern.
  • Message authentication: HMAC-SHA256, never hand-rolled concatenation.
  • Random identifiers: do not use a hash, use a cryptographic random number generator.
  • MD5 and SHA-1: only where an adversary cannot choose the input, and do not introduce new uses.

The author

Francesco Margiotta Casaluci is a backend engineer: he designs and builds microservices in Java and Spring Boot, data pipelines and cloud-native platforms. He writes about what he implements, and he implements the free tools published on this site.

Read the full profile

Related articles