Home All Algorithms File Hash bcrypt Verify Hash Blog MD5 SHA-256 SHA-512 FAQ More Tools
Security

bcrypt vs Argon2 vs scrypt: Password Hashing Compared (2026)

📅 2026-05-12 ⏱ 10 min read ← Back to Blog

If you're building a login system in 2026, you need a password hash function — and not a plain one like SHA-256. You need a function that's deliberately slow, takes a salt, and can be tuned to stay slow as hardware gets faster. The four serious choices are bcrypt, Argon2id, scrypt, and PBKDF2.

The choice between them is less important than the choice not to use plain SHA-256. But the differences matter at the margins, especially for systems handling sensitive data or operating at high scale.

The 2026 short version

  • New project, modern stack: Argon2id. OWASP's first recommendation; memory-hard; designed specifically against modern attacker hardware.
  • Existing bcrypt deployment: stay on bcrypt. It's still secure. Just verify your cost factor is 12 or higher.
  • FIPS-140 / regulatory constraints: PBKDF2 with HMAC-SHA-256, 600,000+ iterations.
  • Memory-constrained environment (mobile, embedded, IoT): bcrypt or PBKDF2. Argon2's memory cost is the point — and the problem.
  • Cryptocurrency / wallet derivation: scrypt is still common (it's what Litecoin uses); otherwise prefer Argon2id.

Why plain hashes don't work for passwords

SHA-256 is designed to be fast. A modern GPU computes ~10 billion SHA-256 hashes per second. An 8-character lowercase password has about 200 billion possibilities — exhausted in 20 seconds. That's why password storage needs algorithms that are deliberately slow, where each hash takes ~100-500 milliseconds. A 100ms hash means an attacker is bottlenecked at 10 attempts/second per GPU thread instead of 10 billion — a 10⁹× security multiplier.

bcrypt: the 25-year veteran

bcrypt was designed by Niels Provos and David Mazières in 1999, built on the Blowfish cipher's expensive key-setup phase. It's been deployed continuously since then with no major vulnerability ever found.

The bcrypt API is simple — one parameter, the cost factor:

// Node.js
const hash = await bcrypt.hash("hunter2", 12);
// Result: $2b$12$N9qo8uLOickgx2ZMRZoMye...

// Verification
const valid = await bcrypt.compare("hunter2", hash);

Cost factor 12 means 2¹² = 4,096 iterations of the key setup. Each increment doubles the work: cost 13 is twice as slow, cost 14 is four times as slow, and so on. As of 2026, OWASP recommends a minimum of 10, with 12 being the comfortable production default.

bcrypt's known weaknesses

Argon2id: the modern recommendation

Argon2 won the 2015 Password Hashing Competition — a multi-year, open contest specifically designed to find a successor to bcrypt and scrypt. It was standardized as RFC 9106 in 2021. Three variants exist: Argon2d (max GPU resistance, vulnerable to side-channel), Argon2i (side-channel resistant, weaker GPU resistance), and Argon2id (hybrid — what you want).

Argon2id has three tunable parameters:

OWASP's 2026 baseline recommendations:

Profilem (memory)t (iterations)p (threads)
Minimum (low-memory)19 MiB (m=19456)21
Recommended64 MiB (m=65536)31
High-security128 MiB (m=131072)3-41

The memory cost is the key innovation. An ASIC attacker building 1,000 Argon2 cores at 64 MiB each needs 64 GiB of on-chip RAM. That's not impossible, but it's vastly more expensive than 1,000 bcrypt cores at 4 KiB each.

scrypt: the in-between

scrypt was published in 2009 by Colin Percival as a memory-hard alternative to bcrypt. It's the basis of Litecoin's proof-of-work and is used in some cryptocurrency wallet derivations. For password storage it's solid but generally superseded by Argon2id, which had the benefit of an open competition and lessons learned from scrypt's design.

Use scrypt only if you have an existing scrypt deployment, or if you specifically need its parameter profile (e.g., a cryptocurrency context).

PBKDF2: the FIPS-compliant choice

PBKDF2 dates to 2000 and is the only one of these four with formal FIPS-140 approval. It uses iterated HMAC (typically HMAC-SHA-256) — many thousands of times — to slow down brute force.

PBKDF2 is widely supported and the safest legacy option, but it's neither memory-hard nor designed for password hashing specifically (it's a key derivation function repurposed for password storage). Modern recommendations: PBKDF2-HMAC-SHA-256 with at least 600,000 iterations for new code where FIPS compliance is required, otherwise prefer Argon2id.

Side-by-side comparison

PropertybcryptArgon2idscryptPBKDF2
Year1999201520092000
Memory-hardNo (4 KB)Yes (configurable)Yes (configurable)No
Max password72 bytesNoneNoneNone
Tuning params1 (cost)3 (m, t, p)3 (N, r, p)1 (iterations)
FIPS-140NoNoNoYes
OWASP rank (2026)3rd (legacy ok)1st2ndFor FIPS only
Library maturityUniversalWideModerateUniversal

The decision tree

  1. Is Argon2id available in your language/framework with a mature library? If yes, use Argon2id with the recommended profile above. Done.
  2. Are you on a memory-constrained platform (mobile auth, embedded)? bcrypt with cost factor 12+. Argon2's memory cost will kill you in concurrent use.
  3. Do you need FIPS-140 compliance? PBKDF2-HMAC-SHA-256 with 600,000+ iterations.
  4. You have existing bcrypt hashes already? Stay on bcrypt. Don't migrate for migration's sake. Verify cost factor is 10+, ideally 12.
  5. None of the above and you're not sure? Use whatever your framework's auth library defaults to. Modern frameworks (Django, Rails, ASP.NET Core, Spring Security) all default to Argon2id or bcrypt with reasonable parameters.

What you should never do

Try the bcrypt generator on this site — it uses the same battle-tested bcryptjs library that bcrypt-generator.com uses. Generate, verify, and experiment with cost factors right in your browser.

Our Network