Comparison
MD5 vs SHA-256 vs bcrypt: When to Use Which Hash
“Just hash the password with SHA-256” is one of the most enduring mistakes in web security. Fast general-purpose hashes and password-hashing functions look similar on the surface but exist for opposite reasons: fast hashes want to hash a lot of data quickly; password hashes want to be slow enough that guessing millions of candidates per second becomes impossible.
The rule is simple: use fast hashes for fingerprints and integrity checks. Use bcrypt (or Argon2, or scrypt) for anything an attacker might try to brute-force.
TL;DR
| MD5 | SHA-256 | bcrypt | |
|---|---|---|---|
| Primary use | Legacy fingerprint (not passwords) | General fingerprint / integrity | Password hashing |
| Collision-resistant | Broken | Yes | Yes |
| Deliberately slow | No | No | Yes (tunable via cost) |
| GPU brute-force per second | billions | billions | ~10K (cost 12) |
| Salt built in | No | No | Yes |
| Output size | 128 bits | 256 bits | 192 bits |
| Safe for passwords | No | No | Yes |
The options in depth
MD5
128-bit fast hash. Broken as a cryptographic hash but still fine as a non-security fingerprint.
MD5 was standardized in 1992 and has been considered cryptographically broken since 2004 — practical collision attacks exist. But not every use of a hash needs collision resistance. As a fingerprint for cache keys, deduplication, or non-adversarial checksums, MD5 is still fast and universally supported.
Good for
- ·Cache keys / dedup where an attacker cannot supply inputs
- ·Non-security checksums (e.g. checksum a build artifact locally)
- ·Legacy interop
Avoid when
- ·Anywhere collision resistance matters (signatures, HMAC — use SHA-256)
- ·Password hashing (never)
- ·Integrity checks against untrusted content
SHA-256
Fast, collision-resistant, the workhorse cryptographic hash of modern systems.
SHA-256 is part of the SHA-2 family, published by NIST in 2001. It is the default fast hash in modern crypto: HMAC-SHA-256, JWT HS256, TLS certificate signatures, Bitcoin, Git object IDs (SHA-1 originally, migrating to SHA-256). No practical attack exists; GPU hardware can compute billions of hashes per second, which is a feature for fingerprinting and a fatal flaw for passwords.
Good for
- ·HMAC / message signing
- ·Integrity checks against untrusted content
- ·Content-addressed storage (like Git)
- ·Deriving cache keys where collision resistance matters
Avoid when
- ·Password hashing (see bcrypt)
bcrypt
Deliberately slow password-hashing function with a tunable cost factor.
bcrypt (Provos & Mazières, 1999) is designed to be slow. A configurable “cost” parameter controls how many rounds of key expansion happen — cost 12 means 2^12 = 4096 rounds, taking roughly 250 ms on modern hardware. That is imperceptible to a real login but reduces GPU brute-force from billions per second to ~10 000 per second.
bcrypt also has a built-in salt (embedded in the output), so you cannot forget to salt — a common bug when hand-rolling password hashing with SHA-256.
Good for
- ·Storing user passwords
- ·Any secret that must resist offline brute-force after a breach
Avoid when
- ·You need very high throughput (hashing millions of items per second — use SHA-256)
Which one should you pick?
→ Is this for storing user passwords?
Use bcrypt (or Argon2id — even better if your language has good support). Do NOT use MD5 or SHA-256 alone.
→ Is this a fingerprint over untrusted content (e.g. verifying a download)?
Use SHA-256. MD5 is trivially forgeable.
→ Is this a fingerprint over trusted content (e.g. a local cache key)?
Either works. MD5 is faster; SHA-256 gives no observable performance hit on modern CPUs.
→ Do I need HMAC?
Use HMAC-SHA-256. HMAC neutralizes MD5's weaknesses in HMAC context, but SHA-256 is the modern default.
Common pitfalls
- ⚠Never salt SHA-256 manually and call it a password hash. Even with a salt, GPUs guess billions of candidates per second.
- ⚠bcrypt truncates inputs longer than 72 bytes. If you accept long passwords, pre-hash with SHA-256 first, or use Argon2.
- ⚠Do not roll your own key stretching (loops of SHA-256). Use a battle-tested library.
- ⚠MD5 is trivially attackable via collision — never use it for content-integrity checks against adversarial input.
Frequently Asked Questions
Is SHA-512 better than SHA-256?
For most uses, no — SHA-256 gives 128-bit collision resistance, which is beyond what any classical attacker can reach. Use SHA-512 only if a spec or interop requires it.
Should I use Argon2 instead of bcrypt?
Argon2id is the modern winner (memory-hard, harder to attack with GPUs/ASICs). Use Argon2id when your language and platform support it well. bcrypt is a solid second choice with broad library support.
Is MD5 completely useless?
No. As a non-security fingerprint (dedupe keys, checksum in a local pipeline) it is fine and still fast. Just never use it where an attacker might supply inputs.
Related comparisons
UUID v4 vs v7
UUID v4 is fully random; UUID v7 is time-ordered. This guide explains when each is the right choice — especially for database primary keys, distributed IDs, and analytics keys.
HS256 vs RS256 vs ES256
HS256 is symmetric (shared secret), RS256 and ES256 are asymmetric (public/private keypair). This guide explains when each JWT signing algorithm is the right choice.