-
Notifications
You must be signed in to change notification settings - Fork 8k
Open
Labels
Description
Description
The password_needs_rehash() function returns true when the new options would downgrade security (e.g., lower cost for bcrypt, lower memory_cost for argon2), which can lead to unintentional weakening of password security.
The following code:
<?php
// Create a hash with high security (cost 12)
$hash = password_hash('test', PASSWORD_BCRYPT, ['cost' => 12]);
echo "Hash created with cost 12: " . substr($hash, 0, 7) . "...\n";
// Check if rehash is needed with LOWER cost (security downgrade)
$needsRehash = password_needs_rehash($hash, PASSWORD_BCRYPT, ['cost' => 5]);
echo "needsRehash (cost 12 -> 5): " . var_export($needsRehash, true) . "\n";
// This is dangerous - application might rehash to weaker security
if ($needsRehash) {
$weakerHash = password_hash('test', PASSWORD_BCRYPT, ['cost' => 5]);
echo "Password downgraded from cost 12 to cost 5!\n";
}Resulted in this output:
Hash created with cost 12: $2y$12$...
needsRehash (cost 12 -> 5): true
Password downgraded from cost 12 to cost 5!
But I expected this output instead:
Hash created with cost 12: $2y$12$...
needsRehash (cost 12 -> 5): false
(no downgrade performed)
Expected behavior
password_needs_rehash() should return false when the new options would weaken security compared to the existing hash. It should only return true for:
- Algorithm changes
- Security upgrades (higher cost, higher memory_cost, etc.)
- Missing/corrupted hashes
Actual behavior
The function returns true for ANY difference in options, including downgrades, which can lead to:
- Accidental security weakening during configuration changes
- Rollback/deployment issues where old config downgrades all passwords
- No protection against misconfiguration
PHP Version
This affects all PHP versions and all password algorithms (bcrypt, argon2i, argon2id)
Operating System
No response