PASSWORD_BCRYPT_SHA256 for password_hash() proposal
Under discussion; not accepted. The official RFC index lists this RFC under discussion (it was listed as a draft on 4 October). At 09:20 UTC on 5 October the author announced the RFC on the internals list. After a page edit at 13:13 UTC the RFC page also reads Under discussion (still version 0.1) and links that announcement as its discussion thread. The earlier conflict between the page header (Draft) and the index is therefore resolved. The voting thread is "tbd", the changelog still has only the 2026-10-04 entry, and no vote has been opened. The author is Sjoerd Langkemper, who also wrote the 72-byte rejection proposal.
What is proposed
The RFC adds a new, opt-in password_hash() algorithm identifier, PASSWORD_BCRYPT_SHA256
(value "bcrypt-sha256"), plus PASSWORD_BCRYPT_SHA256_DEFAULT_COST = 12. The password is first
run through HMAC-SHA256, keyed with the 22-character bcrypt salt string. The base64-encoded
digest (44 bytes) is then passed to bcrypt. That input can't contain NUL bytes and is far below
bcrypt's 72-byte limit, so long passwords are no longer truncated.
- Hashes look like
$bcrypt-sha256$v=2,t=2b,r=<cost>$<salt>$<digest>. The RFC says this is byte-for-byte Passlib'sbcrypt_sha256version 2 format, so PHP and Passlib hashes would be interchangeable. That interoperability claim comes from the RFC and was not tested here. password_verify(),password_needs_rehash(),password_get_info()andpassword_algos()would recognise the new algorithm.costkeeps bcrypt's 4–31 range, and out-of-range values throwValueError.PASSWORD_BCRYPTandPASSWORD_DEFAULTwould not change. Changing the default is listed only as future scope.- The hashes are longer than plain bcrypt hashes, so stored-hash columns may need widening.
- At build level,
ext/standardgains a compile-time dependency onext/hash. The RFC argues this has no practical effect because hash has been always enabled since PHP 7.4.
The vote, when opened, is planned as one question needing a 2/3 majority. The proposed version is the next PHP 8.x ("e.g. PHP 8.7").
Relationship to the 72-byte proposal
This RFC follows from the internals discussion of the
72-byte rejection proposal, where Tim Düsterhus suggested
Passlib's construction instead. The new RFC calls that proposal and php-src PR #21675 (a
Blowfish NUL-byte fix) "previous attempts", and rejects changing PASSWORD_BCRYPT itself as too
risky. In the 5 October announcement, the author wrote that the 72-byte proposal had drawn "much
criticism because of its backwards incompatibility" and that they did not think it "is worth
pursuing further at the moment". The official index now lists that RFC as inactive. Neither
proposal is accepted.
Discussion so far
In the thread on 5 October, Tim Düsterhus supported the
proposal, citing Passlib as precedent. He also argued that the RFC overstates the NUL-byte
problem, because PHP already throws ValueError when a new password contains a NUL byte. He
asked separately whether the $2b$ bcrypt identifier should be supported, saying he understood
it to be identical to $2y$. Another participant asked for a separate "rounds" option. Tim
Düsterhus replied that bcrypt's rounds and PHP's cost are the same parameter, and that
keeping the name cost matches PASSWORD_BCRYPT. These are list comments; the RFC text had not
changed in response when it was inspected on 5 October.
On 8 October Mirco Babin raised three objections:
- Passlib is "not a trusted source for security related issues", and the RFC does not say which
official specification (an IETF RFC or a NIST document) describes
bcrypt_sha256. - The scheme differs from the OWASP Password Storage Cheat Sheet, quoted as recommending
bcrypt(base64(hmac-sha384(password, pepper)))with the pepper kept out of the database. - Hashes may not work with other languages, such as C#, that share a credentials database.
The author replied by asking for a standardized alternative with better interoperability, mentioning PBKDF2, which NIST standardizes but which they called generally less resistant to offline cracking than bcrypt. A participant who signs as Andrey objected to the pace. They said the PR had been written a day after the idea was raised, and asked for time because they have been working on an alternative for weeks and hope to publish it in a week or two. No alternative RFC page was seen. The RFC page inspected on 8 October was unchanged (version 0.1, Under discussion, voting thread "tbd"). On 9 October Rowan Tommins replied to the OWASP objection. They said the "password shucking" attack it describes needs the same inner hash to exist elsewhere for that user, which with a per-hash salted HMAC would need the same password and salt. In their view the salt plays the role of the OWASP pepper. They also noted that OWASP recommends a 72-byte maximum password length, as the inactive length RFC did. The objector replied that such questions belong with OWASP, and that following standards and interoperability is what PHP should offer. Rowan Tommins answered that they had asked no questions. They concluded that the OWASP page describes a weakness in similar algorithms and that the proposed algorithm, while not identical to the OWASP suggestion, addresses the same weakness differently, so it is "worth considering further". These are list opinions; the RFC page was not re-checked in this cycle.
Implementation
The implementation is php-src PR #24073, opened on 2 October 2026 and now titled "ext/standard: bcrypt-sha256 password hash". GitHub labels it "ABI break", and on 2–3 October a core reviewer requested changes, mostly to the tests. As of 8 October it is still open, not marked as a draft, and not merged (last updated 6 October).
Limitations
This page summarises a draft proposal only. Names, format details and the target version can change, and nothing here is available in released PHP. For today's behavior, see bcrypt length limits.