·4 min read

MD5 vs SHA-256: when each one is fine, and when it isn't

MD5 is broken — but not for every job. A practical guide to picking a hash function, including why password hashing needs neither.

Walk into any code review and suggest using MD5 and someone will reflexively say "MD5 is broken, use SHA-256." That's mostly right and often wrong. The honest answer is: it depends what you're using it for. This post walks through the actual differences, where each one is fine, and where neither belongs in the first place.

What a hash function does

A cryptographic hash function takes any input — a string, a file, a million-byte blob — and produces a short fixed-size output called a digest. The same input always produces the same digest; a one-bit change in the input produces a completely different digest. The function is deterministic, fast, and (in theory) one-way: given the digest, you can't reconstruct the input.

A cryptographically secure hash adds two more properties:

  • Pre-image resistance. Given a digest, you can't find an input that produces it.
  • Collision resistance. You can't find two different inputs that produce the same digest.

MD5 fails the second property catastrophically. SHA-256 holds up.

What "MD5 is broken" actually means

In 2004, researchers found a way to construct two different files with the same MD5 hash in a few hours of computation. By 2008, the same technique was used to forge an SSL certificate that fooled real browsers. As of today, you can generate an MD5 collision on a laptop in seconds.

What's important is the kind of attack: this is collision resistance being broken. An attacker can craft two inputs that hash to the same value. That matters anywhere you use a hash to prove something can't be substituted — code signing, digital certificates, integrity-checking a downloaded file when the attacker controls the file.

What hasn't been broken (and probably never will be) is MD5's pre-image resistance. Given an MD5 digest you saw somewhere, you still can't realistically work backwards to the original input. The number of inputs you'd have to try is in the trillions.

That distinction is why MD5 isn't useless — it's just unsuitable for adversarial integrity checks.

When MD5 is still fine

These are non-adversarial uses where collisions are unlikely by accident and the input isn't crafted by an attacker:

  • Cache keys. Hashing a request signature to use as a Redis key. Two different signatures with the same MD5 would be a bug, but no one is attacking your cache.
  • Detecting accidental duplicates. Deduping uploaded files from your own users where collisions, if any, get manually reviewed.
  • Content-addressable storage among trusted writers. Git used SHA-1 (now also vulnerable) for years; the system was designed assuming repository writers are cooperative.
  • Quick checksums for non-security use. "Did this file get corrupted in transit?" MD5 catches every accidental flip.

If your threat model is "the network or disk might silently corrupt my data," MD5 is fast, well-understood, and good enough.

When MD5 is wrong

The moment an attacker can pick the input, switch to SHA-256:

  • Downloading software. A published MD5 lets an attacker who can replace the file also produce a colliding malicious file. This is exactly how Flame malware fooled Windows Update in 2012.
  • Signing or certificates. A trust chain that relies on MD5 collisions is forgeable.
  • Token integrity. If you're hashing a payload to detect tampering, the attacker controls the payload.

For all of these, SHA-256 is the safe default. SHA-512 if you need slightly more headroom; the security level is similar.

Our Hash Generator supports MD5, SHA-1, SHA-256, and SHA-512 — pick the one that matches the threat.

What hashes are not for

The biggest misuse of hash functions is password storage.

Neither MD5 nor SHA-256 is suitable for hashing passwords. Both are designed to be fast — billions of hashes per second on modern GPUs. That speed is exactly what you don't want for passwords, because an attacker who steals your database can try billions of guesses per second.

For passwords, use a password hashing function designed to be deliberately slow and memory-hard:

  • Argon2id — the modern default. Tunable memory cost, designed to resist GPU attacks.
  • bcrypt — well-understood, available everywhere, still good in 2026 with cost factor ≥12.
  • scrypt — memory-hard. Used in some crypto wallets.

Plain SHA-256 of a password, even with a salt, is fast enough that an 8-character password falls in under a day on modest hardware.

Related: if you need a password to start with, the Password Generator uses your browser's CSPRNG and runs entirely client-side.

Quick cheat sheet

Use case Right tool
Cache key, internal dedup MD5 (fast, well-understood)
File integrity from a trusted source MD5 or SHA-256
File integrity from a public source SHA-256
Software signing, certificates SHA-256
Token/payload signing SHA-256 (inside HMAC)
Password storage Argon2id, bcrypt, scrypt
Random unique ID UUID v4, not a hash

A note on speed

Sometimes people pick MD5 for performance. On any laptop in 2026, SHA-256 hashes hundreds of megabytes per second. The difference between MD5 and SHA-256 throughput is rarely the bottleneck — disk I/O, network, or JSON parsing usually is. If you're hashing terabytes of data and benchmarks show SHA-256 is the limit, that's a real reason; otherwise just use SHA-256 and don't think about it.

The shortest possible answer

If a human, an attacker, or a network you don't fully control can pick the input — use SHA-256. If you're hashing your own internal IDs for speed and uniqueness — MD5 is fine. If it's a password — use neither; use Argon2id, bcrypt, or scrypt.

Related tools

Hash Generator (MD5, SHA-256…)Generate MD5, SHA-1, SHA-256, SHA-384, and SHA-512 hashes from text in your browser. Verify checksums without leaking the input.Password GeneratorGenerate strong, random passwords in your browser. Choose length, character types, exclude lookalikes. Nothing is sent to any server.UUID GeneratorGenerate cryptographically random UUIDs (v4) in your browser. Bulk-generate, copy one, or copy all. Nothing leaves your device.
← All posts