Cryptography

Argon2 vs bcrypt vs scrypt: Password Hashing Compared

May 15, 2026 10 min read Haven Team

Three serious password hash functions, three different design philosophies, three sets of trade-offs. Picking between them is not about which is "strongest" — it is about which threat model and operational environment match your application. Here is a clear-eyed comparison.


A password hash is not the same thing as a general-purpose cryptographic hash. SHA-256 is designed to be fast — billions of operations per second on modern hardware. That is excellent for verifying file integrity. It is catastrophic for storing passwords, because the same speed lets attackers test billions of password candidates per second against a stolen database.

A password hash is deliberately slow. More precisely, it is tunable: a parameter lets the application owner choose how much CPU, memory, and parallelism each password verification costs. The defender pays this cost once per login. The attacker pays it once per guess. As long as the cost is calibrated above what your server can absorb during normal use but below user-noticeable latency, you win the asymmetry.

The three candidates that are still cryptographically respectable in 2026 are bcrypt, scrypt, and Argon2. They are listed roughly in order of age.

bcrypt (1999): The Survivor

bcrypt was introduced by Niels Provos and David Mazières at USENIX 1999. It is built around the Blowfish key schedule, intentionally one of the slowest setup phases in any common cipher. The cost parameter (often called the "work factor") is a single integer; each increment doubles the computational cost.

bcrypt's input is capped at 72 bytes. Anything longer is truncated silently, which is a real footgun if you allow long passphrases. Its output is 24 bytes, encoded in a custom alphabet that produces the familiar $2b$12$... format.

What bcrypt does well: it is everywhere. Every major language has a well-tested binding. It has been deployed at scale by companies you have heard of for two and a half decades. The attack literature against it is extensive and mostly reassuring.

What bcrypt does poorly: it uses a small amount of memory (about 4 KB) regardless of work factor. This makes it cheap for an attacker to parallelize on GPUs and ASICs, which have plentiful compute but no special advantage over CPUs on memory-bound workloads. As GPU costs have fallen, bcrypt's effective security has slowly eroded, and pushing the work factor higher to compensate eventually becomes painful for legitimate users.

scrypt (2009): The First Memory-Hard Function

Colin Percival designed scrypt to address bcrypt's GPU/ASIC weakness directly. The key idea: design the function to require a lot of memory, not just a lot of CPU time. Memory is expensive on dedicated hardware. Forcing an attacker to allocate megabytes per guess changes the economics in the defender's favor.

scrypt has three parameters: N (CPU/memory cost), r (block size), and p (parallelization). Tuning them takes some care. A typical interactive-login configuration uses N=2^15, r=8, p=1, which works out to about 32 MB of memory and roughly 100 ms on a 2020-era server.

scrypt is a real cryptographic improvement over bcrypt for password storage, and it has held up well. It is also the proof-of-work function used by Litecoin and Dogecoin, which has resulted in dedicated scrypt-mining ASICs — but those ASICs target very different parameter ranges than password hashing uses, so they don't directly threaten password hash deployments.

Argon2 (2015): The Competition Winner

Argon2 won the Password Hashing Competition in 2015 — a four-year open contest that received 24 submissions from cryptographers worldwide. It was specifically designed to address weaknesses in earlier memory-hard functions and to provide tunable resistance to different attacker models.

Argon2 comes in three variants:

Argon2 takes three parameters: memory cost in KiB, time cost (iterations), and parallelism (threads). OWASP's current 2026 minimums are 19 MiB memory, 2 iterations, 1 thread — though many deployments use considerably more.

The Honest Comparison

Property bcrypt scrypt Argon2id
Year 1999 2009 2015
Memory hardness No (~4 KB) Yes (configurable) Yes (configurable)
Max input length 72 bytes Unlimited Unlimited
Side-channel hardened Partial No Yes (Argon2i/id)
Library ubiquity Excellent Good Good and growing
FIPS-approved No No Not yet

What About PBKDF2?

PBKDF2 (RFC 2898) is older than all three and is still required by many compliance frameworks because it is the only password-based key derivation function approved in FIPS 140. It is iterated HMAC — no memory hardness whatsoever.

PBKDF2 with a strong underlying hash (HMAC-SHA-256 or SHA-512) and a high iteration count is acceptable when regulatory requirements dictate FIPS-only primitives. OWASP's 2026 minimum is 600,000 iterations of PBKDF2-HMAC-SHA-256, though that target rises with hardware. PBKDF2 is also widely used for key derivation (not just verification) in protocols that need a single primitive: Haven, for instance, runs HKDF against a PBKDF2-derived root key for compliance reasons, then layers the rest of its scheme on top.

Outside of FIPS-constrained contexts, PBKDF2 is the weakest reasonable choice.

Migration matters

A common application pattern: re-hash the password on successful login if the stored hash uses old parameters or the wrong algorithm. The user's password is in memory at login time anyway, so this is the right moment to opportunistically upgrade. Most modern hashing libraries expose a needs_rehash() helper for exactly this.

What to Pick in 2026

For a new application with no FIPS constraint: Argon2id, with parameters tuned to your hardware. Start from OWASP's minimums and increase memory cost until login latency reaches your tolerable ceiling (typically 100–500 ms).

For an existing bcrypt deployment with no urgent need to migrate: bcrypt with a work factor of at least 12 is still acceptable. Plan an opportunistic migration to Argon2id when you next touch the auth code.

For a FIPS-constrained environment: PBKDF2-HMAC-SHA-256 with at least 600,000 iterations, and watch for the eventual FIPS approval of Argon2.

What matters more than the choice between these three: salt every hash (modern libraries do this automatically), never store plaintext or reversibly encrypted passwords, never hash with raw SHA-256 or SHA-512, and always pair the hash with rate limiting and breach monitoring. The hash function is the last line of defense after a database compromise, not the first.

Try Haven free for 15 days

Encrypted email and chat in one app. No credit card required.

Get Started →