HashTools
← All posts

Why MD5 Is Broken for Passwords

May 18, 2026·6 min read

"Broken" means something specific here. MD5 has known collision attacks — researchers can produce two different inputs that hash to the same output. That's a genuine problem for integrity checking. But it's not why MD5 fails for passwords.

MD5 is wrong for passwords because it's fast. Extremely fast. A modern GPU can compute around 200 billion MD5 hashes per second. If someone gets a copy of your password database, they can run every common password, every dictionary word, and every common variation against every hash in it before you've had a chance to respond to the breach.

A concrete example

In 2012, LinkedIn was breached. About 6.5 million password hashes — actually SHA-1, which has the same speed problem as MD5 — were posted online. Within days, the majority were cracked. When the full breach turned out to be much larger (117 million accounts in the end), cracking was still fast: the hashes were unsalted, which meant two users with the same password had identical hashes. Cracking one cracked all of them simultaneously.

MD5 would have been worse. On an RTX 4090, hashcat runs MD5 at around 164 billion hashes per second. At that rate, every 8-character password using letters, numbers, and common symbols — roughly 7 quadrillion possibilities — takes about 12 hours. Not days. Hours.

Salts help, but don't fix it

A salt is a random value stored alongside the hash, mixed into the password before hashing. It forces attackers to crack each account individually instead of all at once, which is a real improvement. But it doesn't fix the speed problem.

Even with a unique salt per password, the attacker can still try 164 billion guesses per second per account. Salting converts "crack the whole database at once" into "crack each account at 164 billion guesses per second." That's damage limitation, not a defense.

What makes a password hash actually safe

A password hash function should be slow. Slow enough that an attacker gets a few hundred guesses per second rather than hundreds of billions. The "cost" parameter should be adjustable, so you can make it slower as hardware gets faster over time.

bcrypt does this. At cost factor 12, it takes roughly 250–300ms to compute one hash on a modern server. That's imperceptible to a user logging in and miserable for an attacker. Argon2 and scrypt also add memory requirements, which makes GPU parallelism even harder.

What to use instead

For a new project: Argon2id. It's OWASP's first recommendation, it handles time and memory cost, and it has libraries in every major language.

If Argon2 isn't available in your stack: bcrypt. It's been the standard for 25 years, it's well-audited, and the libraries are everywhere.

If you've inherited a codebase using MD5 or unsalted SHA-1 for passwords: that's a real security issue that should be on the remediation list. The typical approach is to hash the old MD5 hash through bcrypt (wrapping it), then replace it with a proper bcrypt hash the next time the user logs in.

Plain MD5, salted MD5, and unsalted anything are all off the table. The MD5 tool is useful for checksums and legacy systems; see the bcrypt tool for password hashing.