Bcrypt vs Argon2: which password hash in 2026

Bcrypt and Argon2 are the two most widely used password hashing functions today. Both are designed to be slow and resistant to brute-force attacks, unlike MD5 or SHA-256 which are fast by design. Argon2 won the Password Hashing Competition in 2015 and is now the choice recommended by OWASP for new applications. Bcrypt remains an excellent, mature and widely supported option. This article spells out the differences precisely to help you decide.

Why a password hash is different

A classic cryptographic hash such as SHA-256 is designed to be fast: the goal is to hash gigabytes of data per second. For passwords, that property is a flaw: an attacker who obtains your user table can test billions of passwords per second on a GPU. A password hashing function (PHF) on the contrary aims to be:

  • Slow by design, with an adjustable cost parameter
  • Salted, to prevent rainbow tables and parallel attacks across multiple accounts
  • Resistant to specialised hardware (GPU, FPGA, ASIC) to limit the adversarial speedup

The salt and the cost parameter are stored with the hash, in a single string typically of the form $algo$params$salt$hash. This lets you raise the cost over time without forcing immediate migration of old hashes.

Bcrypt: 1999, Blowfish, cost parameter

Bcrypt was designed by Niels Provos and David Mazières for OpenBSD in 1999. It is based on the Blowfish cipher, taking advantage of its expensive table initialisation. Bcrypt exposes a single parameter, cost (or rounds), which sets the iteration count as 2^cost. Increasing cost by 1 doubles the compute time.

Typical output format:

$2y$12$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy
 |  |  |                      |
 |  |  cost = 12               sel + hash en base64
 |  variante (2y = openbsd)
 algo bcrypt

Bcrypt limits the input to 72 bytes: any longer password is silently truncated, a well-known pitfall. The usual workaround is to pre-hash with SHA-256 and base64-encode before bcrypt, but that can introduce problematic null bytes on some implementations. Argon2 has no such limit.

Argon2: 2015, PHC winner, 3 variants

Argon2 was designed by Alex Biryukov, Daniel Dinu and Dmitry Khovratovich. It won the Password Hashing Competition in July 2015 and is standardised by RFC 9106 (2021). Argon2 exposes three parameters:

  • Memory cost (m): amount of memory used, in KiB
  • Time cost (t): number of iterations over the memory block
  • Parallelism (p): number of parallel threads

Argon2 comes in three variants:

  • Argon2d: data-dependent memory access. More resistant to GPU attacks, but vulnerable to side-channel attacks (timing, cache).
  • Argon2i: data-independent memory access. Resistant to side-channels, slightly less resistant to GPU attacks.
  • Argon2id: hybrid, starts in i mode then switches to d mode. Recommended by default by RFC 9106 and OWASP.

OWASP-recommended parameters in 2026 for Argon2id: m=19456 KiB (19 MiB), t=2, p=1. Typical output format:

$argon2id$v=19$m=19456,t=2,p=1$c2VsX2FsZWF0b2lyZQ$aGFzaF9jYWxjdWxl
 |         |   |                  |                 |
 |         |   parametres          sel base64        hash base64
 |         version
 algo argon2id

Why Argon2id is recommended

Resistance to specialised hardware is the decisive criterion today. Bcrypt uses little memory (~4 KiB), which lets a high-end GPU test hundreds of thousands of hashes per second. Argon2id is memory-hard: forcing several MiB of memory per attempt drastically reduces the parallelism achievable on a GPU and makes the design of dedicated ASICs economically unprofitable.

Argon2id's hybrid mode also provides protection against side-channel attacks during the first half of the computation. That combination is what justifies its place as the default recommendation of OWASP, of NIST SP 800-63B (since the 2024 revision) and of RFC 9106.

Comparison table

Criterion Bcrypt Argon2id
Year19992015
StandardisationDe facto, USENIX 1999RFC 9106 (2021)
Parameterscostmemory, time, parallelism
Memory used~4 KiBConfigurable (~19 MiB recommended)
Memory-hardNoYes
GPU resistanceModerateStrong
Side-channel resistanceGood (constant-time)Good (id mode)
Input limit72 bytesNone
OWASP 2026 recommendationAcceptablePreferred
Ecosystem maturityVery wideWide since ~2018

Performance and attack resistance

On a modern server, a bcrypt at cost=12 takes about 250 ms and an argon2id with OWASP parameters about 100-300 ms depending on the machine. Absolute time is not the criterion: what matters is the ratio between your cost (one calculation, once per login) and the attacker's (billions of computations on GPU to crack a dump).

On an RTX 4090, hashcat reaches around 200,000 bcrypt/s at cost=12, versus a few tens of thousands of argon2id at 19 MiB. For the same server-side compute time, Argon2id slows the attacker down 5 to 10 times more than bcrypt, and the gap widens with each new generation of GPUs.

PHP examples

PHP supports both natively via password_hash() and password_verify() since PHP 7.2 for Argon2i (and 7.3 for Argon2id). The PHP constructor handles salt and format automatically.

Bcrypt

$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
$ok   = password_verify($password, $hash);

if (password_needs_rehash($hash, PASSWORD_BCRYPT, ['cost' => 12])) {
    $hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
}

Argon2id

$opts = [
    'memory_cost' => 19456,  // 19 MiB
    'time_cost'   => 2,
    'threads'     => 1,
];
$hash = password_hash($password, PASSWORD_ARGON2ID, $opts);
$ok   = password_verify($password, $hash);

if (password_needs_rehash($hash, PASSWORD_ARGON2ID, $opts)) {
    $hash = password_hash($password, PASSWORD_ARGON2ID, $opts);
}

You can generate or identify hashes of any kind with our hash generator and our hash identifier.

Recommendation

For a new application in 2026, choose Argon2id with the OWASP parameters as a baseline (m=19456, t=2, p=1), adjusted to hit your target time (typically 250 to 500 ms). If you maintain an existing bcrypt-based application, there is no rush to migrate: bcrypt at cost=12 or higher remains safe in 2026. Take advantage of a password_needs_rehash() at the next login to migrate active users to Argon2id gradually.

Absolutely avoid plain MD5, SHA-1 and SHA-256 for passwords (see our MD5 vs SHA-256 comparison). None of these algorithms is designed for that purpose.

Frequently asked questions

Is bcrypt still safe in 2026?

Yes, provided you use a high enough cost (12 minimum, 14 if possible). Bcrypt has no known cryptographic flaw. Its only relative weakness compared to Argon2id is its small memory footprint, which makes it more accessible to GPU and FPGA attacks.

Should I migrate a bcrypt database to Argon2id?

No rush. A gradual migration with password_needs_rehash() is the recommended approach: on each successful login, you re-hash the password with Argon2id. After a few months, the majority of active users are migrated, and you can force a reset for dormant accounts.

What is the right number of threads for Argon2id?

OWASP recommends p=1 by default. Raising p brings nothing if your web server already handles many requests in parallel, and it complicates tuning. Prefer instead to raise m (memory), which is the main lever for GPU resistance.

What is a "bcrypt decrypter"?

There is no such thing as a bcrypt decrypter: the function is one-way by design. Tools that claim to "decrypt" bcrypt merely test dictionaries of common passwords against the hash. That is exactly the same as what an attacker who got hold of your table would do.

Argon2i or Argon2id?

Argon2id in every case for passwords. Argon2i is slightly safer against side-channels but weaker against GPU attacks. Argon2id combines the strengths of both and is explicitly recommended by RFC 9106 for password hashing.

Should I add a pepper on top of the salt?

The salt is enough for the vast majority of applications. A pepper (a secret key stored outside the database and used as an HMAC before the hash) adds a layer in case the database leaks without compromise of the application server. Argon2id does not provide it natively, you have to compose it manually.