Bcrypt vs MD5 vs SHA-256: Which Hash for Passwords, and Why It Matters
“Just hash the password” is some of the most dangerous advice in software, because it hides the question that actually matters: hash it with what? MD5, SHA-256 and bcrypt are all hash functions, but using the first two to store passwords is a well-documented way to get your users’ accounts cracked. Here’s why, in plain terms.
What a hash is — and what it isn’t
A hash function takes any input and produces a fixed-length string. The same input always yields the same output, and you can’t reverse it back to the original. That’s it. You can generate hashes of any text with the hash generator and watch this in action: change one character and the entire output changes.
The trap is assuming all hashes serve the same purpose. They don’t. There are two very different families:
- Fast, general-purpose hashes — MD5, SHA-1, SHA-256. Designed to be fast and to verify data integrity (checksums, signatures, deduplication).
- Slow, deliberate password hashes — bcrypt, scrypt, Argon2. Designed to be slow and to resist brute-force guessing.
For passwords, “fast” is exactly the wrong property.
Why fast hashes are a disaster for passwords
Suppose an attacker steals your database. Every password is stored as a SHA-256 hash. SHA-256 is so fast that modern hardware can compute billions of hashes per second. The attacker doesn’t reverse the hash — they don’t need to. They simply guess: hash “password123”, compare; hash “qwerty”, compare; and rip through enormous dictionaries and leaked-password lists at staggering speed.
It gets worse with rainbow tables — giant precomputed lookups of hash → original for common passwords. If you hashed passwords with plain MD5 or SHA-256, a lot of them can be reversed by lookup alone, instantly.
So the speed that makes SHA-256 great for file checksums makes it catastrophic for passwords. You want password verification to be fast enough for one honest login, but painfully slow when an attacker tries to do it a billion times.
What bcrypt does differently
Bcrypt was built specifically for passwords, and it does three things fast hashes don’t:
-
It’s deliberately slow. Bcrypt has a work factor (also called cost or rounds). Each increment doubles the time it takes to compute. A cost of 12 might take a tenth of a second per hash — unnoticeable for a single login, but it turns “a billion guesses per second” into a crawl.
-
It salts automatically. A salt is random data mixed into each password before hashing, so two users with the same password get completely different hashes. This single-handedly defeats rainbow tables — a precomputed table is useless when every hash is uniquely salted. With bcrypt the salt is generated for you and stored inside the hash itself.
-
It’s future-proof. As hardware gets faster, you simply raise the work factor. The same algorithm stays secure for years; you just turn the dial.
Generate a few bcrypt hashes of the same password with the bcrypt generator and you’ll see it directly: identical input, different output every time, because of the random salt. That’s the behavior you want.
Reading a bcrypt hash
A bcrypt hash isn’t opaque — it’s structured:
$2b$12$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy
$2b$— the bcrypt version.12— the cost factor (here, 2¹² = 4096 rounds).- The next 22 characters — the salt.
- The remainder — the actual hash.
Everything needed to verify a password is bundled in that one string, which is why you don’t store the salt separately.
”But I’m not building a login system”
Even if you never store a password, the same principle decides whether a password is good. A strong password’s value is that it isn’t in any dictionary or leak list an attacker would try first. You can sanity-check the strength and entropy of a password with the password strength checker — and like every tool here, it runs entirely in your browser, so the password you test is never sent anywhere.
When each hash is the right tool
To be clear, MD5 and SHA-256 aren’t “bad” — they’re just for different jobs:
- SHA-256 — verifying a downloaded file matches its published checksum; data integrity; digital signatures. Perfectly appropriate. Generate one with the hash generator.
- MD5 — fast, non-security checksums and deduplication only. Considered broken for anything security-sensitive (collisions are practical), so never use it for passwords or signatures.
- bcrypt / Argon2 / scrypt — storing passwords. Always.
The takeaway
The right mental model is: fast hashes verify data; slow hashes protect passwords. If you’re storing credentials, reach for bcrypt (or Argon2), let it salt automatically, set a sensible work factor (12 is a reasonable starting point in 2026), and raise it over time. If you find yourself about to store a password as MD5 or SHA-256, stop — that’s the exact mistake that turns a database breach into a mass account takeover.