Argon2, bcrypt and scrypt compared for password hashing
Storing a password means storing the output of a deliberately slow hash, never the password itself and never a fast hash like SHA-256. The whole design goal is to make an attacker who steals your database spend an unreasonable amount of time and hardware guessing each password. Three algorithms dominate this space in 2026: bcrypt, scrypt, and Argon2. They differ in what resource they make expensive.
The threat they defend against
An attacker with your password hashes runs offline guesses as fast as their hardware allows. A plain cryptographic hash is catastrophic here because GPUs compute billions of SHA-256 hashes per second. A good password hash is tunable: you dial up its cost so that a single guess takes, say, a quarter of a second on your server, which is invisible to a legitimate login but turns an attacker's billions-per-second into a crawl.
The refinement over time has been about which resource to burn. Making an algorithm CPU-slow is not enough once attackers moved to GPUs and custom ASIC chips, which parallelize CPU-bound work cheaply. The modern answer is memory-hardness: force each guess to use a large block of RAM, because memory is expensive to replicate across thousands of parallel cores.
bcrypt
bcrypt, from 1999, is built on the Blowfish cipher and has a single tuning knob, the cost factor, which sets the number of key-setup rounds as a power of two. A cost of 12 means 2^12 iterations. It is CPU-hard but uses only about 4 KB of memory, so it is not memory-hard in the modern sense. That small fixed memory makes bcrypt more parallelizable on GPUs than scrypt or Argon2.
bcrypt remains a defensible choice. It is battle-tested, implemented everywhere, and has one quirk to remember: it silently truncates input at 72 bytes, so very long passwords lose their tail. Many implementations pre-hash the password before bcrypt to work around this.
scrypt
scrypt, from 2009, was the first widely used memory-hard function. It has three parameters: N (CPU and memory cost, a power of two), r (block size), and p (parallelism). Memory usage is roughly 128 * N * r bytes. By forcing an attacker to hold a large array in memory for each guess, scrypt raises the cost of massively parallel hardware. Its weakness is that the parameters interact in ways that are easy to misconfigure, and a low N quietly removes the memory-hardness that is the entire point.
Argon2
Argon2 won the Password Hashing Competition in 2015 and is the current recommendation. It comes in three variants:
- Argon2d maximizes resistance to GPU cracking but its memory access depends on the data, which can leak timing information.
- Argon2i uses data-independent memory access, resisting side-channel attacks but offering slightly less GPU resistance.
- Argon2id is a hybrid and the one you should use by default. It runs an Argon2i pass first, then Argon2d, getting most of both benefits.
Argon2 exposes three clear parameters: memory cost m, time cost t (iterations), and parallelism p. The separation is cleaner than scrypt's, making it easier to tune memory and time independently.
| Algorithm | Year | Memory-hard | Main parameters | Default choice? |
|---|---|---|---|---|
| bcrypt | 1999 | no (fixed ~4 KB) | cost | acceptable, legacy-friendly |
| scrypt | 2009 | yes | N, r, p | fine if already in use |
| Argon2id | 2015 | yes | m, t, p | recommended for new systems |
What to pick in 2026
For a new system, use Argon2id. A common starting point from the OWASP guidance is 19 MB of memory, a time cost of 2, and parallelism of 1, then measure on your real hardware and raise the memory until a hash takes roughly 250 to 500 ms. If your platform or language lacks a trustworthy Argon2 binding, bcrypt with a cost of 12 or higher is a reasonable fallback, and scrypt is fine if your stack already standardizes on it. Whatever you choose, store the algorithm and its parameters alongside the hash so you can raise the cost later without breaking existing logins.
None of this helps if users pick guessable passwords, since a weak password falls to a dictionary attack regardless of the hash protecting it. Check how long a candidate password would resist guessing with the Password Strength tool before you rely on the hash behind it.