Password Hashing in PHP
In this lesson: Store passwords safely in PHP with password_hash and password_verify — why not md5, rehash and login example. Secure it now.
Never store plain passwords
The single most important rule of login security: never store a password as plain text. If your database is ever stolen, plain passwords are handed straight to the attacker. Instead you store a hash — a scrambled, one-way version — using PHP's built-in functions, which are both easy and very strong.
Hashing a password
When a user signs up, hash their password before saving it.
<?php
$password = "mySecret123";
$hash = password_hash($password, PASSWORD_DEFAULT);
echo $hash; // a long scrambled string
?>
password_hash uses a strong algorithm (bcrypt by default) and adds a random salt automatically. Save this hash in your users table — not the original password.
Verifying at login
At login, compare the entered password to the stored hash.
<?php
$entered = "mySecret123";
$storedHash = "$2y$10$Ku3..."; // from the database
if (password_verify($entered, $storedHash)) {
echo "Login success";
} else {
echo "Wrong password";
}
?>
password_verify checks the entered password against the hash and returns true or false. You never decrypt the hash — you only verify against it.
Why hashing is safe
A hash is one-way: you can turn a password into a hash, but not a hash back into the password. So even if attackers steal your database, they only get scrambled hashes, not usable passwords. The automatic random salt also means two users with the same password get different hashes, defeating precomputed attack tables.
Keeping hashes up to date
<?php
if (password_needs_rehash($storedHash, PASSWORD_DEFAULT)) {
$newHash = password_hash($entered, PASSWORD_DEFAULT);
// save $newHash to the database
}
?>
As PHP improves its default algorithm, password_needs_rehash lets you upgrade old hashes automatically at the next successful login — keeping security current with no user effort.
Common mistakes
- Storing plain passwords. The classic, dangerous mistake — always hash.
- Using old functions like md5 or sha1. These are not safe for passwords; use
password_hash. - Trying to decrypt the hash. Hashes are one-way — verify with
password_verifyinstead. - Adding your own weak salt. Not needed —
password_hashsalts for you.
Summary
- Never store plain passwords — always store a hash.
- Hash with
password_hash($pw, PASSWORD_DEFAULT). - Check logins with
password_verify($entered, $hash). - Hashes are one-way and automatically salted — very safe.
- Use
password_needs_rehashto keep hashes current.
Next, build the full flow in login and registration, or protect the database with prepared statements.
Frequently Asked Questions
Why should I never store passwords as plain text?
What does password_hash do?
password_hash($password, PASSWORD_DEFAULT) turns a password into a long, scrambled hash using a strong algorithm (currently bcrypt). You store this hash, never the original password.How do I check a password at login?
password_verify($entered, $storedHash). It returns true if the entered password matches the stored hash, and false if not. You never "decrypt" the hash — you verify against it.Can I reverse a hash back to the password?
Do I need to add my own salt?
password_hash automatically adds a unique random salt to every hash, so two users with the same password get different hashes. You do not manage the salt yourself.