password_hash() and password_verify()
PHP 5.5 gave developers secure password hashing with the simplest possible API. Two functions. No salt management. No algorithm selection anxiety. It defaults to bcrypt with a reasonable cost, and it's future-proof.
// Hash a password — that's it
$hash = password_hash('correct horse battery staple', PASSWORD_DEFAULT);
// $2y$12$eUz3RiQ... (bcrypt, cost 12, random salt — all automatic)
// Verify — constant-time comparison, safe against timing attacks
if (password_verify($userInput, $storedHash)) {
// Correct password
}
// Future-proof: check if rehashing is needed (algorithm/cost changed)
if (password_needs_rehash($storedHash, PASSWORD_DEFAULT)) {
$newHash = password_hash($userInput, PASSWORD_DEFAULT);
updateStoredHash($userId, $newHash);
}
// Argon2 support (PHP 7.2+)
$hash = password_hash($password, PASSWORD_ARGON2ID, [
'memory_cost' => PASSWORD_ARGON2_DEFAULT_MEMORY_COST,
'time_cost' => PASSWORD_ARGON2_DEFAULT_TIME_COST,
'threads' => PASSWORD_ARGON2_DEFAULT_THREADS,
]);
// Get algorithm info
$info = password_get_info($hash);
// ['algo' => '2y', 'algoName' => 'bcrypt', 'options' => ['cost' => 12]]
The phppassword_hash function generates a random salt automatically, encodes the algorithm and cost in the hash string, and uses a timing-safe comparison. It's nearly impossible to misuse. When PASSWORD_DEFAULT changes to a stronger algorithm in a future PHP version, phppassword_needs_rehash handles the migration transparently.
Significance: Security by Default
Before
password_hash(), developers used md5(), sha1(), or rolled their own salting. The result was millions of insecure password stores. By making the secure approach the easiest approach — literally two functions — PHP eliminated an entire class of security vulnerabilities across its ecosystem.