Re: [RFC][Discussion] Add PASSWORD_BCRYPT_WRAP

From: Date: Fri, 13 Nov 2026 14:51:14 +0000
Subject: Re: [RFC][Discussion] Add PASSWORD_BCRYPT_WRAP
References: 1 2 3 4  Groups: php.internals 
Request: Send a blank email to internals+get-133095@lists.php.net to get a copy of this message
Hi Mirco, On Thu, Nov 12, 2026 at 10:02 PM Mirco Babin <mirco.babin@gmail.com> wrote: > (Mirco Babin) > >Why is the password not validated to be human typable? Repeating > >comment 1: > >- asserts the password is valid utf-8. > >- asserts the password does not contain any ASCII-control-character > > between 0 upto and including 31. > >- asserts the password does not contain the ASCII-control-character > > 127. > >- asserts there are no unicode control characters present. Such as, > > but not limited to, U+202E Right-to-Left Override, U+2066 > > Left-to-Right Isolate, U+2069 Pop Directional Isolate, U+2060 Word > > Joiner, U+00A0 (&nbsp;) No-Break-Space, U+FEFF Byte Order Mark. > > (Andrey Andreev) > >- Because that would violate modern standards like NIST SP 800-63B-4 > > and OWASP ASVS 5 require supporting a length of 64 characters; > > Bcrypts limit is 72 *bytes*. > > (Mirco Babin) > My question is misunderstood. Why does BCRYPT_WRAP not have a very > first step 0 that validates that *password* is human typable, valid > utf-8 and does not contain control characters? Password is input for > the prehash-function, so there is no 72 byte limit. > Your question was not misunderstood. Here's my actual reply verbatim: On Thu, Nov 5, 2026 at 8:13 PM Andrey Andreev <narf@devilix.net> wrote: > To your comments 1 & 2: > - Because none of that would fly and I don't agree with it. You're free to > bring up your suggestions as a separate proposal and see how it goes. :) > - Because that would violate modern standards like NIST SP 800-63B-4 and > OWASP ASVS 5 require supporting a length of 64 characters; Bcrypts limit is > 72 *bytes*. > That was *not* meant as "1 & 2 respectively", but as a general response to both your comments, since both talked about character validation with the strong implication of "character-validated Bcrypt" instead. These two things have a large overlap, especially as you mention Unicode characters, so I am treating them as a package. Let me rephrase more clearly: I am against any character type validation and Bcrypt itself has issues related to character types. Thanks for the link. Why is PBKDF2-HMAC-SHA512 not used? The PBKDF2 > algorithm is much more available in other languages, and enhances > interoperability. E.g. I could not find a cSHAKE256 implementation > for C#. While PBKDF2 is available out of the c# box see: > https://learn.microsoft.com/en-us/dotnet/api/system.security.- > I am not > looking cryptography.rfc2898derivebytes.pbkdf2 > > <https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.rfc2898derivebytes.pbkdf2> > > When a C# and PHP application share a database, with cSHAKE256 it > becomes difficult to seed an initial password from the C# application > into the shared PHP database. > You can use PBKDF2 if you want -- it's already in ext/hash -- but I'm not interested in it being a password_hash() option for a number of reasons: - It is neither memory-hard nor cache-hard. Argon2 won the PHC because it is memory-hard and NIST still favors that property, while cryptographers currently favor Bcrypt for being cache-hard. The only thing everyone agrees on is that PBKDF2 would be a downgrade. - It supports *too many* hash primitives, and its work factor (iterations) varies wildly both with each hash function and in how frequently it needs to be updated. Our current default Bcrypt cost of 12 is good for many years ahead, whereas we'd need to update PBKDF2 recommended settings all the time.. - The previous point makes it very hard to maintain secure defaults both in terms of PHP support and as a broader recommendation. bcrypt-wrap is designed so that you *can* say "just use bcrypt-wrap" and not have to explain details. As for C#'s lack of cSHAKE support - I'd recommend using BouncyCastle anyway; the .NET standard library support for modern crypto is notoriously bad. > (Mirco Babin) > >Why is bcrypt-prehashing needed below 73 password-bytes? Bcrypt can > >handle 72 bytes just fine. > > > >Also 54 binary output bytes of the prehash-function, would truncate > >the password space to 54 bytes. More than 54 password-bytes is going > >to introduce hash-collisions. Assuming the prehash function has no > >collisions within the 54 byte range. > > > >The Bcrypt algorithm truncates the password space beginning at 73 > >password-bytes to 72 bytes. So even the flawed Bcrypt algorithm is > >superior to this invented algorithm. > > > >Why is something being proposed, that deteriorates security? > > (Mirco Babin) > This is not answered. Also using base64 for not having a 0-byte as > input for Bcrypt can be improved. Because this RFC *is* an invented > algorithm why not use Consistent Overhead Byte Stuffing (COBS)? That > would make the pre-hash function output 71 bytes, and COBS would > exactly add 1 byte and remove all 0-bytes from it. That 72 bytes, > not containing any 0-byte. would then be the > "password"-input for Bcrypt. > As I said in my last reply, your remaining questions were already very directly answered in the RFC FAQ. Not only was this not unanswered, it was the very first critique I received and there's a full screen worth of text addressing it (even includes arguments against this new COBS suggestion): https://wiki.php.net/rfc/password_bcrypt_wrap#doesn_t_decreased_input_space_reduce_bcrypt_security > The RFC as is still has no smileys in any example. Please add smileys > into the example in the Proposal section. Like: > > $password = "A really, really long password, that's over 72 bytes > and also includes a nice smiley face 😀"; > > Also it is unwanted that $password contains a 0-byte. It is not human > typable, does not make any sense. It should not be allowed. > If that's what you want, stick to pure Bcrypt. I will not be adding smileys to the example at this time - it is already very obvious that there are no character limitations, and emoji are no more special than any multibyte character. Cheers, Andrey.

« previous php.internals (#133095) next »