Copied from wiki.php.net, last synchronized Oct 13, 2026 11:53 UTC
This RFC proposes to enforce input length limits in password_hash() for PASSWORD_BCRYPT by emitting a deprecation notice in PHP 8.7 and throwing a ValueError in PHP 8.8.
The PASSWORD_BCRYPT algorithm in PHP's password_hash() wraps standard bcrypt. Bcrypt operates on a fixed key schedule with a hard maximum password length of 72 bytes. Any input characters beyond byte 72 are silently discarded.
Historically, PHP has silently truncated inputs longer than 72 bytes. Passing longer strings to password_hash can result in severe authentication bypass vulnerabilities:
When password_hash() is called with PASSWORD_BCRYPT (or PASSWORD_DEFAULT when resolving to bcrypt) and the input $password string exceeds 72 bytes in length:
E_DEPRECATED notice.ValueError.The rockyou password dump contains 772 out of 14344391 passwords that are longer than 72 characters. However, many of those are obvious form spam, keyboard mashing, or just copy/pasted content, not actual passwords. I couldn't find an obvious actual password in the set. This is not conclusive, since passwords can be any string and don't have to look like passwords.
Adobe's 2013 breach contains 152989508 passwords encrypted with an 8-byte block cipher. The longest password is 11 blocks (88 bytes), but it's the same block 10 times, indicating a repetitive password. There's one password that takes up 9 blocks (72 bytes), and several that take up 7 blocks (56 bytes).
So depending on how you look at it, passwords longer than 72 characters occur between never and 0.005% of the time.
In PHP's exception hierarchy, a ValueError indicates a programming error rather than a runtime operational/input error that an application should catch and recover from dynamically.
One might argue that receiving a long string is a dynamic runtime input error. However, throwing a ValueError is appropriate here because exceeding 72 bytes in password_hash() is fundamentally a programming error for two reasons:
password_hash() exceed this threshold, it almost exclusively indicates that developers are improperly concatenating static pepper secrets, nonces, or secondary hashes into the password field before passing it into password_hash().password_hash() with raw input exceeding algorithm bounds without prior validation or pre-hashing represents a developer oversight in design rather than an unexpected end-user input state.Throwing a ValueError ensures developers catch this misconfiguration during development and testing rather than allowing insecure hashing patterns into production.
This RFC explicitly does not modify password_verify().
Applying a failure or exception to password_verify() for inputs exceeding 72 bytes would introduce a severe backward-compatibility break. Existing users who registered under previous versions with passphrases longer than 72 bytes (or whose applications prepended long secrets) would be permanently unable to authenticate. Leaving password_verify() untouched preserves access for existing credentials while preventing the creation of new truncated hashes.
// Valid passwords (<= 72 bytes) work normally across all versions:
$hash = password_hash('correct-horse-battery-staple', PASSWORD_BCRYPT);
// Passwords > 72 bytes:
// PHP 8.7 Behavior:
// E_DEPRECATED: password_hash(): Passing a password longer than 72 bytes to the bcrypt algorithm is deprecated
$longPassword = str_repeat('a', 80);
$hash = password_hash($longPassword, PASSWORD_BCRYPT);
// PHP 8.8+ Behavior:
try {
$hash = password_hash($longPassword, PASSWORD_BCRYPT);
} catch (ValueError $e) {
// Throws: ValueError: password_hash(): Password length cannot exceed 72 bytes when using PASSWORD_BCRYPT
}
password_hash() with PASSWORD_BCRYPT will trigger an E_DEPRECATED notice.password_hash() with PASSWORD_BCRYPT will throw a ValueError, failing unhandled calls.Applications allowing long passphrases or prepending pepper/nonces should validate password length, pre-hash input (e.g. using raw SHA-256/SHA-512 outputs before passing to bcrypt), or migrate to algorithms without 72-byte restrictions, such as Argon2id (PASSWORD_ARGON2ID).
ValueError.Frameworks and authentication libraries that permit arbitrary-length input strings or prepend pepper secret strings will need to enforce length validation or pre-hashing before calling password_hash().
None.
None.
Opposition arguments:
password_needs_rehash()) could still surface the error for existing users with long passwords when algorithm parameters change.Support arguments:
None at present.
password_verify() without introducing authentication lockouts for existing legacy hashes (e.g., via opt-in flags or distinct verification modes).PASSWORD_ARGON2ID), which do not suffer from the 72-byte key truncation limit.Primary Vote: Requires 2/3 majority.
Vote: Throw error on bcrypt passwords longer than 72 bytes as described in the RFC? — Yes: 0 · No: 0 · Abstain: 0 (closed)