[PHP-DEV] [RFC] Throw error for passwords longer than 72 bytes in password_hash() with bcrypt

Hi Tim,

On Wed, Sep 30, 2026 at 9:03 PM Tim Düsterhus <tim@bastelstu.be> wrote:

https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-63B-4.pdf#subsubsection.3.1.1

You are correct in that the NIST standard specifies that:

  1. Verifiers SHALL request the password to be provided in full (not a
    subset of it) and SHALL verify the entire submitted password (e.g., not
    truncate it)

However: The NIST standard applies to the “Verifier” (i.e. the
application), not to the primitive. While password_hash() is certainly
intended to be usable as-is, an application requiring strict compliance
with all SHALLs and SHOULDs of the NIST standard already needs to
perform some steps that cannot be solved by password_hash(), such as
verifying that known-insecure passwords cannot be used. And when trying
for pedantic compliance with NIST you cannot use BCrypt at all, since
BCrypt technically is not in the list of NIST-approved hashing
functions. For that you need an approved hash function, and my latest
knowledge is that neither BCrypt nor Argon2’s BLAKE2b primitive are
acceptable. In practice this means using hash_pbkdf2().

I pointed to NIST SP 800-63 as the root source, but not the only standard. If I pointed to the OWASP ASVS for example, most of what you wrote would be irrelevant, but my basis - the correct implication of the bytes vs characters distinction - is still proven. All of the math arguments you’ve brought up previously are eroded by that, and I really must say it - deceiving developers and end-users about behavior is not a math problem to begin with.

What you’re technically correct on is the Verifier vs “primitive” (not really a primitive in the true sense of that term). However, obfuscating bcrypt’s deficiencies is actively reducing developers’ capacity to compensate for that, and leaving them with a false sense of security.

If we ignore all that, implementing the RFC would mean that BCrypt
hashing with PHP would start to deviate from a combination of two
different requirements:

  1. Verifiers and CSPs SHOULD permit a maximum password length of at
    least 64 characters.

and

  1. Verifiers and CSPs SHOULD accept Unicode [ISO/ISC 10646] characters
    in passwords. Each Unicode code point SHALL be counted as a single
    character when evaluating password length.

The RFC would thus trade a SHALL violation for a SHOULD deviation that
affects exactly the users using non-ASCII character sets.

I don’t see an added SHALL violation; the RFC is only making an already-present limitation visible.

And while the effective length is reduced for e.g. CJK characters, they
are also much more information dense than ASCII characters. An English
word taking up 5-7 bytes can often be represented as a single 3-byte CJK
character. Of course the RFC also does nothing about this: Instead of
reducing the effective length, inputs exceeding “the effective length”
are rejected, forcing the user to pick a shorter password. The
achievable security ceiling is the same - and high enough.

Might be true for CJK; not true for Cyrilic, Greek - halved in length and strength no matter how you look at it. And I’m not mentioning others simply because I’m not familiar with them, but there are multiple.

The NUL byte point is moot, because NUL bytes are already rejected
during hashing. For that I agree with the ValueError / check, since the
truncation on NUL is much more catastrophic - and because actually
including a NUL in a legit user-provided password is much more
complicated than exceeding a 72 byte limit. In practice the Internet has
also converged on “just using UTF-8”.

I admit I keep forgetting that the NUL byte thing was already patched. The point isn’t entirely moot still, but not worth arguing third-order effects and we have plenty of other disagreements, so be it.

I don’t necessarily disagree with the BCrypt truncation being a problem,
but in this case the cure is worse than the disease.

As long as you recognize the problem, I don’t think we’d be far apart. I absolutely recognize the BC break as a major concern that might take higher precedence. Until now though, your position has been a lot closer to “no problem here at all” than “I draw the line at breaking existing applications”.

Cheers,
Andrey.

On 30 September 2026 16:47:30 BST, "Tim Düsterhus" <tim@bastelstu.be> wrote:

I would. This is in fact almost exactly the behavior of the classic `CRYPT_STD_DES` algorithm, except the limit is 8 bytes (with the high bit ignored) with a 64 bit internal state: Even if the additional characters would not be ignored, the 64 bit state means that there are equivalent inputs of 8 bytes or fewer for inputs of 9 bytes or more.

Let's follow this example a bit:

If a system used CRYPT_STD_DES, and limited user input to 8 bytes, you might have colliding hashes for "password" and "@7&jp9Q -".

If the system did *not* limit user entry, it would have colliding hashes for "password1234" and "password !!! password". Note that both would pass a check for "include at least one digit or punctuation mark", but both would actually be breached by someone trying the input "password" which has neither.

Now, truncating at 72 bytes is obviously very different from truncating at 8, but it's possible to imagine scenarios where it could lead to a meaningful loss of entropy. A quick search found this alphabet: <https://en.wikipedia.org/wiki/Osage_script&gt; Stored high enough in Unicode that it requires 4 bytes of UTF-8 per character, *and* requires combining diacritics for some sounds. A diceware password of words in that script might truncate at 3 or 4 words.

More likely, as already discussed, a developer misuses the API and prefixes a password, cutting the effective length limit.

It seems to me that refusing those inputs and alerting the developer to the limitation leaves the *overall system* more secure.

Hi Kamil, Tim,

Replying to two messages in one here to cut down on traffic...

On 30 September 2026 17:53:57 BST, Kamil Tekiela <tekiela246@gmail.com> wrote:

From a user's POV, it doesn't, and I agree with that. But that's not
very important for what we are discussing here. If it works as
designed, then it works correctly.

I think this is the crux of our disagreement: I don't understand why the user's POV is "not very important".

Rowan Tommins
[IMSoP]

Hi

On 2026-09-30 22:01, Andrey Andreev wrote:

I pointed to NIST SP 800-63 as the root source, but not the only
standard. If I pointed to the OWASP ASVS for example, most of what you
wrote would be irrelevant, but my basis - the correct implication of the
bytes vs characters distinction - is still proven. All of the math
arguments you've brought up previously are eroded by that, and I really
must say it - deceiving developers and end-users about behavior is not a
math problem to begin with.

Even with a non-ASCII 2-byte per character diceware password you are at roughly 50 bits of entropy in the 72 bytes, which makes the math go from “an attacker that started at the big bang still wouldn't have cracked it” to “a dedicated attacker with 20_000 GPUs at hand might be able to crack a single password within a year” (given the current default BCrypt cost of 12 and 1.5kH/s/GPU which is within the range you mentioned in the Argon2 thread). And as further elaborated below, the RFC does not change that ceiling and turns the “not a math problem” into a usability problem.

The RFC would thus trade a SHALL violation for a SHOULD deviation that
affects exactly the users using non-ASCII character sets.

I don't see an added SHALL violation; the RFC is only making an
already-present limitation visible.

I said that it would be trading a SHALL for a SHOULD, not that it would add new SHALL violations. This is theoretically better when going purely based on standard reading, but does not improve the real world situation.

Might be true for CJK; not true for Cyrilic, Greek - halved in length and
strength no matter how you look at it. And I'm not mentioning others simply
because I'm not familiar with them, but there are multiple.

The conclusion remains the same: The user picks a shorter password and you are back to square 1. And of course telling the user “your password may be at most 72 bytes in length” when they don't know what bytes are and why some characters are more than 1 byte (so they can't even count the number of bullets in the password input to check if their password fits) will just lead to frustrated users picking much weaker passwords instead.

I don't necessarily disagree with the BCrypt truncation being a problem,
but in this case the cure is worse than the disease.

As long as you recognize the problem, I don't think we'd be far apart. I
absolutely recognize the BC break as a major concern that might take higher
precedence. Until now though, your position has been a lot closer to "no
problem here at all" than "I draw the line at breaking existing
applications".

Your interpretation is not quite correct. My position is roughly “it sure would be better if BCrypt wouldn't have the truncation limit, but that ship has sailed”. My main issue with this proposal is not the “breaking existing applications” bit, but “forcing applications to expose the byte limitation to the non-technical end user”. The RFC is turning a theoretical security issue (for genuine passwords) into actual usability issues for non-technical users who learned “longer = better”.

Best regards
Tim Düsterhus

Hi

On 2026-09-30 23:04, Rowan Tommins [IMSoP] wrote:

Let's follow this example a bit:

If a system used CRYPT_STD_DES, and limited user input to 8 bytes, you might have colliding hashes for "password" and "@7&jp9Q -".

If the system did *not* limit user entry, it would have colliding hashes for "password1234" and "password !!! password". Note that both would pass a check for "include at least one digit or punctuation mark", but both would actually be breached by someone trying the input "password" which has neither.

Yes, but looping back to the initial example you provided: Someone using the strong randomly generated password "@7&jp9Q -" might still be breached by someone trying "password", a property of the small state space and why DES crypt is no longer secure.

Now, truncating at 72 bytes is obviously very different from truncating at 8, but it's possible to imagine scenarios where it could lead to a meaningful loss of entropy.

Indeed for BCrypt the situation is quite different: The 72-byte prefix is only guessable if it is predictable on its own (e.g. someone selecting their favorite lyrics). In that case the password is weak with or without the suffix, since you can just plug in the prefix into a search engine and look up how the song continues. The RFC will do nothing for them: They are just going to pick the same song, but cut the lyrics after one verse rather than two.

A quick search found this alphabet: <https://en.wikipedia.org/wiki/Osage_script&gt; Stored high enough in Unicode that it requires 4 bytes of UTF-8 per character, *and* requires combining diacritics for some sounds. A diceware password of words in that script might truncate at 3 or 4 words.

The same applies to Osage: The user is limited to the same 3 to 4 words and will go with those rather than figuring out something more secure. See also my reply to Andrey.

More likely, as already discussed, a developer misuses the API and prefixes a password, cutting the effective length limit.

It seems to me that refusing those inputs and alerting the developer to the limitation leaves the *overall system* more secure.

My expectation is that developers who are “alerted” to the limitation will just go with whatever solution makes the error message go away the quickest instead of trying to understand the impact, leaving the overall system in a less secure state. Incorrect prehashing would be a good example here: In an attempt to “fix” BCrypt’s length limitation, folks have passed the *raw* output of a hash function to BCrypt, resulting in NUL-termination becoming relevant and thus reducing security more than the 72-byte limit ever could. Now the NUL-termination issue is caught by PHP nowadays, but I'm positive that folks will figure out equally fragile workarounds. The obvious one being `substr($password, 0, 72)` which mimics the status quo, but would *carry forward* the issue once `PASSWORD_DEFAULT` changes from BCrypt to something else, whatever it may be.

Best regards
Tim Düsterhus

On 30 September 2026 22:26:21 BST, "Tim Düsterhus" <tim@bastelstu.be> wrote:

Even with a non-ASCII 2-byte per character diceware password you are at roughly 50 bits of entropy in the 72 bytes, which makes the math...

I don't think there maths and entropy etc, is the major problem for me with this proposal.

The problem for me is that this a scary BC break.

If a user of a site has a silly long password now, they can still login. If this changes to an Exception, then they no longer can, without intervention from a site owner, for whom there is now BC break in the language throwing random new exceptions *based on user input*.

I'm going to be -1 on this one.

cheers
Derick

I appreciate the debate on this topic, and I am in support of the RFC. It sounds to me like the API has been lost in the debate though.

We all agree Bcrypt is working as intended.

What we are seeing in password_hash() is an unhelpful API. The function accepts an input of arbitrary length, but the manual contradicts the arbitrary length usage with a not-entirely-accurate "Caution" block about the length of the input. It specifically says PASSWORD_BCRYPT, and misses the identical concerns with PASSWORD_DEFAULT or null.

What the manual doesn't illustrate is a real case where password_verify() doesn't verify the password.

$hash = password_hash('one two three four five six seven eight nine ten eleven twelve thirteen epic secure password', PASSWORD_DEFAULT);

$result = password_verify('one two three four five six seven eight nine ten eleven twelve thirteen ', $hash);

var_dump($result);

A developer might ask why the application is doing this, but the RFC asks why is PHP doing this? Is the function named password_verify going to verify the password or not?

_____________
Robert Chapin

On Thu, Oct 1, 2026, at 00:11, Derick Rethans wrote:

The problem for me is that this a scary BC break.

Yes. I think the BC break is worth it, but I understand how opinions may differ on this.

If this changes to an Exception, then they no longer can [login]

Sort of. I intentionally only proposed changing password_hash and not password_verify. However, password_hash may still be used in the login flow, so login may fail for long passwords but this depends on the application logic.

Is there anything you could think of that would improve the situation but would potentially have your approval? First switch the default password hash from bcrypt to something else? Increase the length at which an exception is thrown? Not an exception but a warning?

Regards,

Sjoerd

Hi Tim,

On 30 September 2026 23:07:45 BST, "Tim Düsterhus" <tim@bastelstu.be> wrote:

The same applies to Osage: The user is limited to the same 3 to 4 words and will go with those rather than figuring out something more secure.

Would they? If I'm asked for a 6-character password, I don't go to a diceware list and pick one word.

Worst case, they do just use those 3 words, and they're no worse off than before. Best case, they pick a different type of password and gain security. I don't see a scenario where they end up with something *worse*.

`substr($password, 0, 72)` which mimics the status quo, but would *carry forward* the issue once `PASSWORD_DEFAULT` changes from BCrypt to something else, whatever it may be.

As a developer, I have three options of how to deal with the bcrypt limitation:

1) reject longer passwords
2) truncate longer passwords
3) use a different algorithm

At the moment, if I don't choose explicitly, the implementation chooses option 2 for me. The RFC changes that to option 1, *but I still have the exact same choices*.

Doing the truncation explicitly would mean I can correctly perform additional validation, such as looking up on haveibeenpwned, using the truncated string, not the full input.

I would even argue that keeping the truncation after switching algorithm might be a valid choice, at least in a rehashing flow; because otherwise I am "rehashing" an input which might be varying every time the user types it, rather than the part of the string actually being verified.

On the other hand, rejecting instead of truncating would mean I can correctly handle things like "must not match previously used password". And the user has the *chance* to change their behaviour based on the limitation, rather than being lied to.

Neither solution is great, and yes, plenty of developers won't think it through, and plenty of users will set terrible passwords either way; but by making the limitation more noticeable, we at least give people a chance to do something about it.

Rowan Tommins
[IMSoP]

Hi

On 2026-10-01 08:57, Sjoerd Langkemper wrote:

Is there anything you could think of that would improve the situation but would potentially have your approval? First switch the default password hash from bcrypt to something else? Increase the length at which an exception is thrown? Not an exception but a warning?

PHP Warnings are commonly converted to Exceptions by a throwing error handler, particularly when using one of the major frameworks. The native ErrorException exists just for this purpose. For a significant number of applications emitting a warning is equivalent to throwing an Exception.

Regarding the length increase my understanding is that the argument in favor of the RFC is that “silently truncating inputs is a security issue”, so increasing the length would keep the security issue, while also keeping the usability issue.

------

For PASSWORD_BCRYPT the only acceptable option to me is “leave it alone”. Generally speaking user-provided passwords must never throw (with the possible exception of ASCII control characters, including NUL).

To provide a constructive suggestion: Borrowing passlib’s `bcrypt-sha256` (passlib.hash.bcrypt_sha256 - BCrypt+SHA256 — Passlib v1.7.4 Documentation) algorithm (including the output format) might be a valid option for a well-defined pre-hashing solution.

In fact even your RFC gets pre-hashing wrong by specifying that folks should pass the raw prehash to BCrypt, which would result in a ValueError for 12% of users (for SHA-256) due to a NUL byte appearing in the raw output - and catastrophic NUL truncation if PHP would not be checking for NUL. This is the kind of fragile workaround that I mentioned in my reply to Rowan (php.internals: Re: [RFC] Throw error for passwords longer than 72 bytes in password_hash() with bcrypt).

Best regards
Tim Düsterhus

On Thu, Oct 1, 2026, at 10:21, Tim Düsterhus wrote:

To provide a constructive suggestion: Borrowing passlib’s
bcrypt-sha256

algorithm (including the output format) might be a valid option for a
well-defined pre-hashing solution.

Yes, having another password hashing algorithm that does not truncate (like bcrypt) and is included by default (unlike argon2) would be great.

However, I was under the impression that this was problematic, seeing the lack of progress on yescrypt. Perhaps bcrypt-sha256 is different since we already have both fundamental functions built in?

yescrypt PR: https://github.com/php/php-src/pull/16452

Regards,

Sjoerd

Hi again,

Before I go into a more lengthy response, a quick reply to Robert, because his question keeps popping up outside of this RFC too:

On Thu, Oct 1, 2026 at 1:43 AM Robert Chapin <php@miqrogroove.com> wrote:

A developer might ask why the application is doing this, but the RFC
asks why is PHP doing this? Is the function named password_verify going
to verify the password or not?

password_verify() remains unchanged on purpose, and that’s a good thing.
There is some natural compulsion to make it consistent with password_hash(), but it’s a trap that would break old passwords for no benefit. I would oppose any such change.

On Thu, Oct 1, 2026 at 12:26 AM Tim Düsterhus <tim@bastelstu.be> wrote:

Even with a non-ASCII 2-byte per character diceware password you are at
roughly 50 bits of entropy in the 72 bytes, which makes the math go from
“an attacker that started at the big bang still wouldn’t have cracked
it” to “a dedicated attacker with 20_000 GPUs at hand might be able to
crack a single password within a year” (given the current default BCrypt
cost of 12 and 1.5kH/s/GPU which is within the range you mentioned in
the Argon2 thread). And as further elaborated below, the RFC does not
change that ceiling and turns the “not a math problem” into a usability
problem.

See, but you keep claiming it’s a usability problem while defending it as a math problem, and being very selective about it too - you alone keep bringing up diceware. It’s not the only plausible way to exceed the limit.

I don’t see an added SHALL violation; the RFC is only making an
already-present limitation visible.

I said that it would be trading a SHALL for a SHOULD, not that it would
add new SHALL violations. This is theoretically better when going purely
based on standard reading, but does not improve the real world
situation.

Sorry about my imprecise wording, but I did follow the logical consequence of the trade to mean that, in order to satisfy SHOULDs you’d be violating a SHALL. Maybe you meant it the other way around … Unimportant, just wanted to clear the air.

Might be true for CJK; not true for Cyrilic, Greek - halved in length
and
strength no matter how you look at it. And I’m not mentioning others
simply
because I’m not familiar with them, but there are multiple.

The conclusion remains the same: The user picks a shorter password and
you are back to square 1. And of course telling the user “your password
may be at most 72 bytes in length” when they don’t know what bytes are
and why some characters are more than 1 byte (so they can’t even count
the number of bullets in the password input to check if their password
fits) will just lead to frustrated users picking much weaker passwords
instead.

That’s sweeping a lot of details under the rug.

  • Saying that users will choose weaker passwords, while at the same time standing on the argument that length difference at that ceiling is irrelevant. I can see what you meant non-maliciously, but I’m sure you too can see how that’s having it both ways and not a fair representation.
  • The average user, for whom we have observations and can make some assumptions about, is not the one choosing extreme-length passwords. The limit will be hit either by people who have an affinity for security OR by users who are victims of problems constructed upstream from them (such as prefixes added by developers and corporate IT staff, for reasons right or wrong). In the latter case, raising an error is the only way to make these these upstream issues visible.
  • While a poor way to construct passwords, some users will choose a constant prefix and then a suffix based on the domain name they’re accessing (or functionally equivalent unique identifier). If the prefix is long enough, silent truncation is completely eliminating the user’s ability to know that they no longer have unique passwords (however flawed their method was), in turn making them vulnerable to more types of attacks. Note that passwords get exposed in ways other than cracking hashes, like accidental (or even intentional) logging, so that’s not a prerequisite.
  • We are (for obvious reasons) looking at the whole thing from a server-side perspective, but where any burden is shifted onto the end user, there is a client side and input field limits are very much a thing.

How the 1-byte or 2-byte characters disctinction is handled, if at all possible, is indeed a real problem. Now we have progress!

Your interpretation is not quite correct. My position is roughly “it
sure would be better if BCrypt wouldn’t have the truncation limit, but
that ship has sailed”. My main issue with this proposal is not the
“breaking existing applications” bit, but “forcing applications to
expose the byte limitation to the non-technical end user”. The RFC is
turning a theoretical security issue (for genuine passwords) into actual
usability issues for non-technical users who learned “longer = better”.

Fair enough, though we’ll have to agree to disagree on the ship sailed argument.

On Thu, Oct 1, 2026 at 1:10 AM Tim Düsterhus <tim@bastelstu.be> wrote:

My expectation is that developers who are “alerted” to the limitation
will just go with whatever solution makes the error message go away the
quickest instead of trying to understand the impact, leaving the overall
system in a less secure state.

Silent truncation by PHP itself is no different in principle. Dressing up the same fallacy because we think we know better than the affected parties is just putting lipstick on a pig.

On Thu, Oct 1, 2026 at 11:21 AM Tim Düsterhus <tim@bastelstu.be> wrote:

To provide a constructive suggestion: Borrowing passlib’s
bcrypt-sha256
(https://passlib.readthedocs.io/en/stable/lib/passlib.hash.bcrypt_sha256.html)
algorithm (including the output format) might be a valid option for a
well-defined pre-hashing solution.

I am actually preparing something based on the same principle, but didn’t want to bring it up prematurely. I think this RFC has merit on its own and have seen way too many proposals be killed on the promise of something else in the uncertain future.

Cheers,
Andrey.

On 01/10/2026 12:11 am, Derick Rethans wrote:

On 30 September 2026 22:26:21 BST, "Tim Düsterhus" <tim@bastelstu.be> wrote:

If a user of a site has a silly long password now, they can still login. If this changes to an Exception, then they no longer can, without intervention from a site owner, for whom there is now BC break in the language throwing random new exceptions *based on user input*.

I agree with Derick's concerns. This change could affect users who chose long passwords because they believed they would be more secure. I don't believe those users should be \'affected.

I support changing the default to argon2, but this change will be a -1 from me as well.

--
Regards,

Jordi Kroon

On Thu, Oct 1, 2026, 8:01 AM Jordi Kroon <jordikroon@me.com> wrote:

On 01/10/2026 12:11 am, Derick Rethans wrote:

On 30 September 2026 22:26:21 BST, “Tim Düsterhus” <tim@bastelstu.be> wrote:

If a user of a site has a silly long password now, they can still login. If this changes to an Exception, then they no longer can, without intervention from a site owner, for whom there is now BC break in the language throwing random new exceptions based on user input.

I agree with Derick’s concerns. This change could affect users who chose
long passwords because they believed they would be more secure. I don’t
believe those users should be 'affected.

Please folks, read the RFC before parroting this line.

The RFC only proposes changing password_hash(), NOT password_verify().

If a hash already exists from a truncated password, it will continue to validate. The only time this would raise the exception or error is when hashing, which will typically be done once, when a user registers, or chooses to change their password. Having an error condition here forces the application developer to address the truncation issue when storing new hashes only, and won’t invalidate existing user hashes and login attempts.

–
Matthew Weier O’Phinney
mweierophinney@gmail.com
https://mwop.net/
he/him

On Thu, 1 Oct 2026 at 18:15, Matthew Weier O'Phinney
<mweierophinney@gmail.com> wrote:

If a hash already exists from a truncated password, it will continue to validate. The only time this would raise the exception or error is when hashing, which will typically be done once, when a user registers, or chooses to change their password. Having an error condition here forces the application developer to address the truncation issue when storing new hashes only, and won't invalidate existing user hashes and login attempts.

Small correction. Rehashing is commonly done during login, not registration.

-----Original Message-----

It will still match. A hash of 72-byte long password and a hash of
73-byte long password where the first 72 bytes are the same will match.
Proofpoint - ZenWeb™
8.5.11&d=DwIFaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=i0NKIgJ
vrKCThBAHo8lLTC9DcIc_YQfpu9rIABLCJDI&m=BfKD0IS6H873YHy61CdrQdPZPt8HtJQQ
ssJtrmymWnZI8VB-PIfGO_Be4ovErFMc&s=ctggKP-MeLZgXCyZvKx30hgf4i3E-uSaRhl9
_u92xHY&e=

Yes, and that is a false positive - the user provides the wrong password, and the system lets them in.

Rowan Tommins
[IMSoP]

=====

For what it's worth, I stumbled across this issue recently in the older part of our PHP codebase. After coming up with a solution, we forced PW resets for the impacted users. And, to Rowan's point, if this had thrown an exception (or even a warning, tbh) during any PHP version upgrade we would've caught it many years ago.

Looking through the lens of software security in 2026, I cannot think of any situation where this function should silently accept more bytes than it can hash.

Thank you all for your work on the PHP project.

-Jeff (non-voter, trying to influence the vote)

-----Original Message-----
From: Tim Düsterhus <tim@bastelstu.be>
Sent: Wednesday, September 30, 2026 6:08 PM
To: Rowan Tommins [IMSoP] <imsop.php@rwec.co.uk>
Cc: internals@lists.php.net
Subject: Re: [PHP-DEV] [RFC] Throw error for passwords longer than 72 bytes in password_hash() with bcrypt

It seems to me that refusing those inputs and alerting the developer
to the limitation leaves the *overall system* more secure.

My expectation is that developers who are “alerted” to the limitation will just go with whatever solution makes the error message go away the quickest instead of trying to understand the impact

=====

If that's the case, then the "throw" proposal is an obvious win. Developers who would do as you feel have an easy remedy. Those who are competent are warned of a significant security issue, that they can properly analyze and resolve.

-Jeff

Hi

On 2026-10-01 13:02, Sjoerd Langkemper wrote:

However, I was under the impression that this was problematic, seeing the lack of progress on yescrypt. Perhaps bcrypt-sha256 is different since we already have both fundamental functions built in?

The problems are with including extra libraries. A minimal build of PHP should be possible without installing any extra libraries, which means that libraries are vendored into php-src as necessary. This comes with the usual problems of vendoring, such as keeping libraries up to date. Yescrypt likely doesn't provide enough benefit for the extra maintenance effort.

For bcrypt-sha256 this situation is different, since all the necessary primitives are already always-available.

For reference to the other readers, Sjoerd already opened a PR with an implementation: bcrypt_sha256 by Sjord · Pull Request #24073 · php/php-src · GitHub. There are some technical nits, but I don't see anything fundamentally wrong with it.

Best regards
Tim Düsterhus