Password hashing parameters: Argon2id, bcrypt, scrypt & PBKDF2
The current OWASP-recommended settings for storing passwords, quoted from the source, with the attack speed we measured for each setting on a real GPU, and a calculator that measures your own device to find the right PBKDF2 iteration count. If you run a service, this is the one decision that turns a breach from a catastrophe into a shrug.
OWASP's guidance: use Argon2id; if it is not available, scrypt. bcrypt is for legacy systems, and PBKDF2 for systems that must be FIPS-140 compliant.
Argon2id (first choice)
Any one row is acceptable: pick by how much memory your server can spare. Use the id variant.
| Memory (m) | Iterations (t) | Parallelism (p) | Attack speed, Radeon 8060S |
|---|---|---|---|
| 47104 KiB (46 MiB) | 1 | 1 | 2,014/s |
| 19456 KiB (19 MiB) | 2 | 1 | 2,011/s |
| 12288 KiB (12 MiB) | 3 | 1 | not measured |
| 9216 KiB (9 MiB) | 4 | 1 | not measured |
| 7168 KiB (7 MiB) | 5 | 1 | 2,009/s |
scrypt (second choice)
| N (cost) | r (block) | p (parallelism) | Attack speed, Radeon 8060S |
|---|---|---|---|
| 2^17 (128 MiB) | 8 | 1 | 177/s |
| 2^16 (64 MiB) | 8 | 2 | not measured |
| 2^15 (32 MiB) | 8 | 3 | not measured |
| 2^14 (16 MiB) | 8 | 5 | not measured |
| 2^13 (8 MiB) | 8 | 10 | not measured |
bcrypt (legacy)
Work factor (cost) of at least 10, as high as your login-latency budget allows. Maximum input length is 72 bytes in most implementations, so either enforce a 72-byte maximum or pre-hash with a peppered HMAC as OWASP describes (see choosing a password hash for the traps). Use only where Argon2id and scrypt are unavailable. We measured 318 guesses per second against cost 12 on the Radeon 8060S. Each step of cost doubles the work, so cost 10 is about 1,270 per second and cost 14 about 80.
PBKDF2 (FIPS / legacy)
| PRF | Iterations | Note | Attack speed, Radeon 8060S |
|---|---|---|---|
| PBKDF2-HMAC-SHA256 | 600,000 | OWASP recommended | 3,816/s |
| PBKDF2-HMAC-SHA512 | 220,000 | 2,963/s | |
| PBKDF2-HMAC-SHA1 | 1,400,000 | legacy only | not measured |
What the attack speeds mean
The speed column is how many guesses per second hashcat 7.1.2 managed against a hash made with that exact setting, on the AMD Radeon 8060S in our test machine. Lower is better for the defender.
- The OWASP minimums are not equal-cost settings. At these settings scrypt (177 per second) and bcrypt at cost 12 (318) were the hardest to attack, Argon2id about 2,010, and PBKDF2 3,000 to 4,000: about a 22-fold spread. OWASP prefers Argon2id for its design, which it describes as balancing resistance to side-channel and GPU attacks, not because its minimum is the slowest to crack. Raise any of them when your login budget allows.
- The three Argon2id rows we measured were indistinguishable on this hardware, as OWASP's "equal level of defense" says they should be. Method and controls are on the hash rates page.
- A common password falls behind any of them. Trying the 100,000 most common leaked passwords against one stolen hash takes this GPU about 50 seconds at the Argon2id rate, 5 minutes at bcrypt cost 12 and 9 minutes at scrypt. Pair any setting with a blocklist of common and compromised passwords, as NIST SP 800-63B-4 requires.
Calibrate PBKDF2 for your device
Runs PBKDF2-HMAC-SHA256 in your browser to find the iteration count that hits a target time on this hardware. Compare it against the 600,000 floor, and never go lower. Runs entirely locally.