[PHP-DEV] [Discussion] Changing PASSWORD_DEFAULT to Argon2

Hi all,

I’d like to gather opinions on the possibility of switching PASSWORD_DEFAULT from bcrypt to Argon2id.

A few reasons to do so:

  • bcrypt has a limit of (and silently truncates at) 72 bytes, which may seem like an acceptable thing at first glance, but does cause many headaches
  • Argon2 is superior in every way and widely recognized as the gold standard today; I’ve even encountered people who mistakenly believed it is already PHP’s default
  • While both algorithms are (by today’s understanding) considered safe from quantum threat, Argon2’s memory hardness makes it future-proof by design

But there is one contentious circumstance - bcrypt is entirely bundled with PHP, while Argon2 has external dependencies: libargon2, libsodium, or (since PHP 8.4) openssl. The addition of OpenSSL is key, because it’s the most ubiquitous and a practical must for almost any environment, IMO making changing PASSWORD_DEFAULT viable. But am I right to think that, or is any external dependency likely to kill the proposal? That’s what I want to gauge before fleshing out an RFC with the greater detail it deserves.

Cheers,
Andrey.

On Fri, Sep 18, 2026, at 22:20, Andrey Andreev wrote:

But there is one contentious circumstance - bcrypt is entirely bundled with PHP, while Argon2 has external dependencies: libargon2, libsodium, or (since PHP 8.4) openssl.

This is both a con and pro. Using a crypto library instead of a roll-your-own solution seems a very wise decision to me. Not to say that I don’t trust the php bcrypt implementation. Just saying this as a general rule.

Greetings, Casper

On 18/09/2026 23:20, Andrey Andreev wrote:

Hi all,

I'd like to gather opinions on the possibility of switching PASSWORD_DEFAULT from bcrypt to Argon2id.

A few reasons to do so:
- bcrypt has a limit of (and silently truncates at) 72 bytes, which may seem like an acceptable thing at first glance, but does cause many headaches
- Argon2 is superior in every way and widely recognized as the gold standard today; I've even encountered people who mistakenly believed it is already PHP's default
- While both algorithms are (by today's understanding) considered safe from quantum threat, Argon2's memory hardness makes it future-proof by design

But there is one contentious circumstance - bcrypt is entirely bundled with PHP, while Argon2 has external dependencies: libargon2, libsodium, or (since PHP 8.4) openssl. The addition of OpenSSL is key, because it's the most ubiquitous and a practical must for almost any environment, IMO making changing PASSWORD_DEFAULT viable. But am I right to think that, or is any external dependency likely to kill the proposal? That's what I want to gauge before fleshing out an RFC with the greater detail it deserves.

Cheers,
Andrey.

Hi Andrey

Did anything change since the last time?

--
Anton

Hi Anton,

On Sat, Sep 19, 2026 at 5:15 AM Anton Smirnov <sandfox@sandfox.me> wrote:

Did anything change since the last time?

https://externals.io/message/120993#120996

Yes, that thread is from September 2023, more than a year before PHP 8.4’s release bringing in the --with-openssl-argon2 flag.
libargon2 and libsodium can’t be relied upon to exist on most systems, but openssl is a very different beast.

There already exists a year-old proposal to enable --with-openssl-argon2 by default (https://github.com/php/php-src/pull/19360). It would be fair to point out that I am thinking ahead of it, this is exploring potential and there are plenty of subsequent problems to debate after. But whether the openssl dependency is acceptable is the most critical one.

Cheers,
Andrey.

On 19/09/2026 12:26, Andrey Andreev wrote:

Hi Anton,

On Sat, Sep 19, 2026 at 5:15 AM Anton Smirnov <sandfox@sandfox.me <mailto:sandfox@sandfox.me>> wrote:

    Did anything change since the last time?

    PASSWORD_DEFAULT value - Externals <https://externals.io/
    message/120993#120996>

Yes, that thread is from September 2023, more than a year before PHP 8.4's release bringing in the --with-openssl-argon2 flag.
libargon2 and libsodium can't be relied upon to exist on most systems, but openssl is a very different beast.

There already exists a year-old proposal to enable --with-openssl-argon2 by default (enable openssl-argon2 by default by henderkes · Pull Request #19360 · php/php-src · GitHub <https:// github.com/php/php-src/pull/19360>). It would be fair to point out that I am thinking ahead of it, this is exploring potential and there are plenty of subsequent problems to debate after. But whether the openssl dependency is acceptable is the most critical one.

Cheers,
Andrey.

My point is mostly about this part:

Argon2 for settings that are reasonable for interactive
authentication is worse than BCrypt

Like, if there were any successful attacks on bcrypt that negate that part

On Sat, Sep 19, 2026 at 11:00 PM Anton Smirnov <sandfox@sandfox.me> wrote:

My point is mostly about this part:

Argon2 for settings that are reasonable for interactive
authentication is worse than BCrypt

Like, if there were any successful attacks on bcrypt that negate that part

Yes and no.

That part was based on a tweet from 2019, based on many unknowns (parameters, hardware, worse by how much, etc.) very broadly saying sub-1000ms.

By 2023, we have slightly more clarity and comparable strenghts at just over 500ms: https://infosec.exchange/@epixoip/110912922574721750 (note that it looks somewhat scary because of the large memory cost, but time cost is always 1; very different from PHP’s defaults)
At that same time the bar is described as anywhere between sub40-100ms for bcrypt and above 400-1000ms argon2, I guess with no clear winner in between? https://infosec.exchange/@sc00bz/110228557196895869

In the meantime, all of this benchmark-centric talk is missing the forest for a tree, as cracking either algorithm is practically infeasible but vanilla bcrypt has more serious issues relevant to the average developer: https://soatok.blog/2024/11/27/beyond-bcrypt/
All of the “bcrypt is stronger for auth” people have their own versions of how to solve its non-computational weaknesses too, they do recognize the problem, but people who care mostly about benchmarks and maths will only talk about the benchmarks and maths. :slight_smile:

This can be a very contentious subject, and I don’t want to go down the rabbit hole if the much simpler matter of dependencies would kill the argument anyway, hence my original question. If for a moment we assume Argon2id is better, can we rely on OpenSSL for default?

Cheers,
Andrey.

On Sun, Sep 20, 2026 at 3:49 PM Andrey Andreev <narf@devilix.net> wrote:

On Sat, Sep 19, 2026 at 11:00 PM Anton Smirnov <sandfox@sandfox.me> wrote:

My point is mostly about this part:

Argon2 for settings that are reasonable for interactive
authentication is worse than BCrypt

Like, if there were any successful attacks on bcrypt that negate that part

Yes and no.

That part was based on a tweet from 2019, based on many unknowns (parameters, hardware, worse by how much, etc.) very broadly saying sub-1000ms.

By 2023, we have slightly more clarity and comparable strenghts at just over 500ms: https://infosec.exchange/@epixoip/110912922574721750 (note that it looks somewhat scary because of the large memory cost, but time cost is always 1; very different from PHP’s defaults)
At that same time the bar is described as anywhere between sub40-100ms for bcrypt and above 400-1000ms argon2, I guess with no clear winner in between? https://infosec.exchange/@sc00bz/110228557196895869

In the meantime, all of this benchmark-centric talk is missing the forest for a tree, as cracking either algorithm is practically infeasible but vanilla bcrypt has more serious issues relevant to the average developer: https://soatok.blog/2024/11/27/beyond-bcrypt/
All of the “bcrypt is stronger for auth” people have their own versions of how to solve its non-computational weaknesses too, they do recognize the problem, but people who care mostly about benchmarks and maths will only talk about the benchmarks and maths. :slight_smile:

This can be a very contentious subject, and I don’t want to go down the rabbit hole if the much simpler matter of dependencies would kill the argument anyway, hence my original question. If for a moment we assume Argon2id is better, can we rely on OpenSSL for default?

OpenSSL is an external shared library so it cannot be always enabled. I don’t think we want to bundle it which is kind or requirement for always enabled extensions. If we wanted to add some strict dependecy and treat it pretty much in libc category, then it would need an RFC on its own. But even if this was changed, then we still support 1.1.1 and will support 3.0 for some time too even after we drop 1.1.1 so I think we would need to wait for much longer anyway.

Kind regards,

Jakub

Hi

On 2026-09-20 15:46, Andrey Andreev wrote:

By 2023, we have slightly more clarity and comparable strenghts at just
over 500ms: Jeremi M Gosney :verified:: "@adamshostack @Viss@mastodon.social yeah, we kind…" - Infosec Exchange (note that
it looks somewhat scary because of the large memory cost, but time cost is
always 1; very different from PHP's defaults)

500ms is insanely long for interactive authentication. And the memory cost in that example benchmark is indeed scary when you consider that PHP ships with a default memory_limit of 128 MB (though it seems that the Argon2 hashing is not included in the memory_limit accounting).

Best regards
Tim Düsterhus

Hi Tim,

On Mon, Sep 21, 2026 at 8:11 PM Tim Düsterhus <tim@bastelstu.be> wrote:

500ms is insanely long for interactive authentication. And the memory
cost in that example benchmark is indeed scary when you consider that
PHP ships with a default memory_limit of 128 MB (though it seems that
the Argon2 hashing is not included in the memory_limit accounting).

That’s missing the point I was making …

The cited 1000ms had at least halved in 4 years (if the screenshot was up to date at the time), and it’s been an additional 3 years since.
Hashcat didn’t even ship with Argon2 support until last year, so verifying the benchmarks (if they are direct and not math projections) was extremely hard.

PHP’s defaults are m=64mb,t=4,p=1, which averages around 240ms on my 10y laptop, same as bcrypt cost 12.
When Hashcat 7 did release last year it came with a benchmark for m=64mb,t=3,p=1 yielding around 1.7k hashes per second: https://hashcat.net/wiki/doku.php?id=hashcat
For bcrypt cost=12 I’ve seen rates ranging from 1k to 2k H/s using the same GPU model (some variance in setups/optimizations I guess).

All of this is comparing ceilings well beyond safe recommendations, somewhat like top speeds on a racing car; there’s a solid argument that e.g. 48mb or even 32mb is plenty enough.

But anyway, if Jakub’s comment was describing the status-quo, it’s just not happening.

Cheers,
Andrey.

On Sun, Sep 20, 2026, at 16:44, Jakub Zelenka wrote:

On Sun, Sep 20, 2026 at 3:49 PM Andrey Andreev <narf@devilix.net> wrote:

On Sat, Sep 19, 2026 at 11:00 PM Anton Smirnov <sandfox@sandfox.me> wrote:

If for a moment we assume Argon2id is better, can we rely on OpenSSL for default?

OpenSSL is an external shared library so it cannot be always enabled.

Is it a possibility to set argon2 as default when PHP is compiled with OpenSSL, and bcrypt otherwise?

Regards,

Sjoerd Langkemper

Hi

On 2026-09-25 08:59, Sjoerd Langkemper wrote:

Is it a possibility to set argon2 as default when PHP is compiled with OpenSSL, and bcrypt otherwise?

Randomly changing defaults based on the build environment provide for a terrible user experience. In particular this would also mean that for “rolling upgrades” of your PHP version or other mixed environments some of your application servers might be unable to verify hashes created by other application servers.

Best regards
Tim Düsterhus