When developers compare MD5 vs SHA-256 vs bcrypt for storing passwords, the usual advice is "MD5 is broken, use SHA-256." That advice is wrong, and it is the single most common security mistake in this space. MD5 is broken, yes. But raw SHA-256 is also a poor choice for passwords, for a completely different reason: it is too fast. The right answer is a deliberately slow algorithm built for passwords, which means bcrypt or Argon2.
This guide makes the distinction the rest of the SERP skips. We will cover why fast hashes lose to GPUs, what salting and work factors actually do, and exactly which algorithm to reach for in 2026. You can test each hash type yourself in the browser as we go.
MD5 vs SHA-256 vs bcrypt at a Glance#
The core mistake is treating all hashing as one job. It is two different jobs with opposite requirements. File integrity wants a fast hash. Password storage wants a slow one. Confusing them is how breached databases get cracked in hours.
| Algorithm | Type | Speed | Salt built in | Safe for passwords? | Good for |
|---|---|---|---|---|---|
| MD5 | Fast hash | Extremely fast | No | No (broken) | Nothing security-related |
| SHA-1 | Fast hash | Very fast | No | No (broken) | Legacy compatibility only |
| SHA-256 | Fast hash | Very fast | No | No (too fast) | File checksums, integrity, signatures |
| bcrypt | Slow hash (KDF) | Tunable, slow | Yes | Yes | Password storage |
| Argon2id | Slow hash (KDF) | Tunable, slow | Yes | Yes (current best) | Password storage |
| PBKDF2 | Slow hash (KDF) | Tunable, slow | Yes (you add it) | Yes (acceptable) | FIPS-constrained environments |
Key takeaway: SHA-256 is excellent at the job it was designed for (proving a file was not altered) and unsafe at a job it was never designed for (resisting password-cracking hardware). "Secure hash" does not mean "secure for passwords."
The word "secure" causes most of the confusion. SHA-256 is a member of the SHA-2 family, and it is cryptographically secure in the sense that you cannot find collisions or reverse it mathematically. That property is what file integrity needs. Password storage needs something else entirely: resistance to brute force at scale.
Why MD5 Is Broken (and SHA-1 With It)#
MD5 fails on two fronts. First, it is collision-broken: researchers can deliberately produce two different inputs with the same MD5 digest, which destroys its value for signatures and certificates. SHA-1 fell the same way with the practical collision work published in 2017.
Second, and more relevant for passwords, MD5 is blisteringly fast. A modern GPU can compute billions of MD5 hashes per second. That speed is a feature for a checksum and a catastrophe for a password hash.
Here is what that speed means in practice. If a site stores passwords as plain MD5 and the database leaks, an attacker with a single consumer graphics card can test an enormous dictionary of common passwords against every account almost instantly. Add a precomputed rainbow table (a giant lookup of hash to plaintext) and unsalted MD5 hashes of common passwords reverse in milliseconds.
- MD5: collision-broken, far too fast, no salt. Never use it for security.
- SHA-1: collision-broken since 2017, too fast. Deprecated everywhere.
- The lesson: "broken" here is partly about collisions and partly about raw speed.
You can still safely use MD5 or SHA-256 for non-adversarial corruption checks (did this file download intact?). That is integrity, not authenticity, and not password storage. For anything an attacker would want to forge or crack, MD5 is out.
The SHA-256 Trap: Secure but Too Fast for Passwords#
This is the part most comparisons get wrong. SHA-256 is not collision-broken. It is a genuinely strong cryptographic hash. So why is it the wrong tool for passwords?
Because it is fast on purpose. SHA-256 was designed so that systems can hash large amounts of data quickly to verify integrity. A high-end GPU rig can compute on the order of billions of SHA-256 hashes per second. When the algorithm is fast, the attacker's brute-force machine is fast too.
Password cracking is an offline guessing game. Once an attacker has your hash database, nothing rate-limits them. They are not logging into your site one attempt at a time. They are running your hashes against wordlists and mutation rules on dedicated hardware. The faster your hash function, the more guesses per second they get, and the cheaper every cracked password becomes.
Salting helps, but does not fix speed#
A common rebuttal is "just salt your SHA-256." A salt is a unique random value stored alongside each hash and mixed into the input before hashing. Salting is essential, and it does two real things:
- It defeats rainbow tables, because a precomputed table is useless against per-user random salts.
- It ensures two users with the same password get different hashes, so cracking one does not crack the other.
But salting does nothing about speed. An attacker still cracks each salted SHA-256 hash one at a time at billions of guesses per second. Salt removes the bulk-precomputation shortcut; it does not make the underlying function slow. That is why "salted SHA-256" is better than naked SHA-256 and still not good enough for passwords.
The mental model: salt protects against precomputation. A slow algorithm protects against raw brute-force throughput. You need both, and SHA-256 only gives you one of them.
What bcrypt Does Differently: Slow on Purpose#
bcrypt was designed in 1999 specifically for password storage, and its central idea is the opposite of MD5 and SHA-256: it is deliberately, tunably slow. bcrypt bundles three things a password hash needs.
- A built-in salt. bcrypt generates and stores a per-hash salt automatically, so you cannot forget to add one.
- A work factor (the "cost"). This is a number you set that controls how many internal iterations bcrypt runs. Each increment of one roughly doubles the time to compute a hash.
- An adaptive design. As hardware gets faster, you raise the work factor to keep hashing slow, without changing algorithms.
A bcrypt hash string carries its own parameters. A typical hash looks like $2b$12$R9h/cIPz0gi..., where $2b$ is the bcrypt version, 12 is the work factor (cost), and the rest is the salt and digest combined. That self-describing format means verification needs only the stored hash, not a separate salt column.
The point of the work factor is to make each single guess expensive. If one bcrypt hash takes a quarter of a second to compute, an attacker who could do billions of SHA-256 guesses per second is now reduced to a handful of bcrypt guesses per second per core. The same wordlist that cracks SHA-256 in minutes might take years against well-configured bcrypt.
Choosing a bcrypt work factor#
The work factor is a tradeoff between security and your own server's login latency. Set it so a single hash takes a noticeable but tolerable amount of time on your hardware, commonly tuned to land somewhere in the range of 0.1 to 0.5 seconds per hash.
- A higher cost is more secure but slows every login and every signup.
- Benchmark on your actual production hardware, not your laptop. Faster servers can afford a higher cost.
- Re-evaluate yearly. Hardware improves, so a cost that was painful for attackers in 2020 is cheaper now.
bcrypt also has one quirk worth knowing: it truncates input at 72 bytes. If you support very long passphrases or pre-hash passwords (a pattern some teams use), test that behavior so you do not silently ignore characters past the limit.
Where Argon2 Fits (and PBKDF2)#
bcrypt is excellent and still a perfectly defensible choice in 2026. But the current top recommendation from security guidance like the OWASP password storage cheat sheet is Argon2id, the winner of the 2015 Password Hashing Competition.
Argon2id improves on bcrypt by being memory-hard. bcrypt's work factor costs CPU time, but it uses little memory, which means attackers can pack many bcrypt-cracking cores onto cheap hardware. Argon2id lets you tune three knobs: time cost (iterations), memory cost (how much RAM each hash needs), and parallelism. Forcing each guess to consume meaningful memory blunts the GPU and ASIC advantage that makes cracking cheap.
| Algorithm | Resists GPU cracking | Memory-hard | When to choose it |
|---|---|---|---|
| Argon2id | Strong | Yes | New systems; the current default recommendation |
| bcrypt | Strong | No | Mature, battle-tested; fine for existing systems |
| scrypt | Strong | Yes | Valid memory-hard alternative if Argon2 is unavailable |
| PBKDF2 | Moderate | No | FIPS-140 compliance requirements; use high iteration counts |
PBKDF2 deserves a mention because it shows up in regulated environments. It is older and not memory-hard, so it resists GPUs less well than bcrypt or Argon2. But it is FIPS-approved, which matters for government and some enterprise work. If you must use PBKDF2, push the iteration count high (hundreds of thousands to millions, tuned to your latency budget).
The short version of the decision tree:
- New project with no constraints: use Argon2id.
- Existing system already on bcrypt and working: bcrypt is fine, keep it, raise the cost over time.
- FIPS or strict compliance environment: PBKDF2 with a very high iteration count.
- Never: MD5, SHA-1, raw SHA-256, raw SHA-512, or any unsalted fast hash.
Test Each Hash Yourself#
Reading about hashes is one thing. Seeing them is another, and it makes the speed difference click. You can generate MD5, SHA-1, SHA-256, and SHA-512 digests of the same input in the browser to see how each algorithm transforms text.
Paste a sample string like correct horse battery staple into the free hash generator and watch it produce each digest instantly. That instant result is exactly the problem with fast hashes for passwords: if your browser computes a SHA-256 digest with zero perceptible delay, imagine a GPU farm doing billions of them per second against a leaked database.
A few things to try as you experiment:
- Hash the same word twice. Note that MD5 and SHA-256 give the identical output every time, which is why they need an external salt and why rainbow tables work against them.
- Change one character. The whole digest changes completely (the avalanche effect), which is good for integrity checks.
- Compare digest lengths. SHA-256 is longer than MD5, but length alone does not make it safe for passwords. Speed is the real issue.
Note: a browser-side fast-hash tool is the right way to learn what these algorithms produce, but it is not where you should generate production password hashes. bcrypt and Argon2 belong server-side in your auth library, never in client JavaScript.
While you are thinking about credential security, it is worth checking how resistant your own passwords are. A strong password and a slow hash work together: weak passwords fall to any hash, and a great hash cannot fully save a password that is in every wordlist. Run a few through the password strength checker to see how guessability and entropy factor in, and generate genuinely random ones with the secure password generator so the cracking math is on your side.
Common Mistakes to Avoid#
The theory is simple, but the same implementation errors show up in breach after breach. Watch for these.
- Using SHA-256 because it is "more secure than MD5." It is, against collisions. It is still too fast for passwords. This is the trap this whole article exists to flag.
- Rolling your own scheme like
sha256(sha256(password) + salt). Stacking fast hashes does not make a slow hash. Use a real password KDF. - Storing the salt wrong or reusing one global salt. Salts must be unique and random per user. bcrypt and Argon2 handle this for you, which is one more reason to use them.
- Setting a work factor once and never raising it. A cost that hurt attackers years ago is cheap now. Revisit it.
- Hashing passwords in client-side JavaScript. The hash must happen on the server. A client-side hash just becomes the new password an attacker replays.
If you are also handling tokens rather than just stored passwords, the same "use the right primitive" logic applies to signatures and verification. Our guide on decoding vs verifying a JWT covers a closely related mistake: trusting a token you only decoded but never cryptographically verified.
The Verdict on MD5 vs SHA-256 vs bcrypt#
For password storage, the ranking is not close. MD5 is broken and far too fast. SHA-256 is cryptographically strong but still too fast, even when salted, so it loses to GPU brute force the moment your database leaks. bcrypt and Argon2id are slow on purpose, salt automatically, and let you raise the cost as hardware improves, which is exactly what password storage demands.
So when someone hands you the MD5 vs SHA-256 vs bcrypt question for passwords, the answer is bcrypt or Argon2id, every time. Reserve SHA-256 for what it is genuinely great at, like file integrity and checksums, and never let a "secure hash" label trick you into using a fast algorithm where a slow one belongs. Test each digest in the free hash generator to make the speed difference concrete, then keep the slow, password-specific algorithms in your auth layer where they belong.
Frequently Asked Questions#
Is SHA-256 secure for passwords? No, even though SHA-256 itself is a strong, unbroken cryptographic hash. The problem is speed: SHA-256 is designed to be fast, so an attacker with a leaked database can brute-force billions of guesses per second on a GPU. Salting helps against rainbow tables but does not slow the algorithm down. For passwords, use a deliberately slow function like bcrypt or Argon2id instead.
Why is bcrypt better than SHA-256 for passwords? bcrypt is intentionally slow and adjustable, while SHA-256 is intentionally fast. bcrypt includes a built-in salt and a tunable work factor, so each individual password guess costs an attacker real time and money. As hardware improves, you raise the work factor to keep cracking expensive. SHA-256 gives attackers cheap, high-throughput guessing, which is the opposite of what password storage needs.
Should I use bcrypt or Argon2 in 2026? Both are solid. Argon2id is the current top recommendation because it is memory-hard, which blunts the GPU and ASIC advantage that makes cracking cheap. bcrypt remains a perfectly defensible, battle-tested choice, especially if your system already uses it. For a brand-new project with no compliance constraints, default to Argon2id; if you are already on bcrypt and tuning the cost, there is no urgent reason to migrate.
Is salting enough to make SHA-256 safe for passwords? No. Salting is necessary and you should always do it, but it only solves one problem: it defeats precomputed rainbow tables and ensures identical passwords produce different hashes. Salting does nothing about the algorithm's speed, so an attacker still cracks each salted SHA-256 hash at billions of guesses per second. You need both a unique salt and a slow algorithm, which is exactly what bcrypt and Argon2 provide.
Is MD5 safe to use for anything? Only for non-security corruption checks, like confirming a file downloaded without errors. MD5 is collision-broken, so it must never be used for digital signatures, certificates, passwords, or anything an attacker might want to forge or crack. Even for file integrity against a real adversary, prefer SHA-256. You can see how MD5 compares to other digests using a free hash generator.
What is a work factor in bcrypt? The work factor (also called the cost) is a number that controls how many internal iterations bcrypt performs. Each increment of one roughly doubles the time to compute a single hash. You set it so one hash takes a small but noticeable fraction of a second on your production hardware, which keeps logins fast for you while making mass cracking slow for attackers. Raise it over time as hardware gets faster.



