Secure PHP Password Storage: md5, password_hash, and crypt Explained with Code
This guide walks through three common PHP password‑hashing techniques—md5, password_hash (BCrypt), and crypt—showing complete registration and login code samples, highlighting security drawbacks of md5 and recommending stronger, salted hashing for safe user authentication.
Password Hashing in PHP
1. Using md5 (insecure)
The md5 function produces a 32‑character hash but does not use a salt and is vulnerable to collisions and brute‑force attacks. It should never be used for production password storage.
<?php
// Registration
$username = $_POST['username'];
$password = $_POST['password'];
$hashed = md5($password); // insecure
// Store $hashed in the database
// Login
$input = $_POST['password'];
if (md5($input) === $stored_hash) {
// authenticated (but insecure)
}
?>2. Using password_hash (recommended)
PHP 5.5+ provides password_hash, which automatically selects a strong algorithm (default PASSWORD_BCRYPT), generates a random salt, and stores the salt together with the hash. Verification is performed with password_verify.
<?php
// Registration
$username = $_POST['username'];
$password = $_POST['password'];
$hash = password_hash($password, PASSWORD_DEFAULT); // bcrypt with random salt
// Store $hash in the database
// Login
$input = $_POST['password'];
$stored_hash = $row['password']; // fetched from DB
if (password_verify($input, $stored_hash)) {
// login successful
} else {
// invalid credentials
}
?> password_hashhandles salting, algorithm upgrades, and provides resistance against modern attacks, making it the preferred method.
3. Using crypt with a manual salt
The low‑level crypt function can be used with a manually generated salt (e.g., via random_bytes or openssl_random_pseudo_bytes). The salt must include the algorithm identifier, such as $2y$10$ for bcrypt with a cost of 10.
<?php
// Registration
$username = $_POST['username'];
$password = $_POST['password'];
// Generate a 22‑character base64 salt
$salt = substr(str_replace('+', '.', base64_encode(random_bytes(16))), 0, 22);
$hash = crypt($password, '$2y$10$' . $salt); // bcrypt with manual salt
// Store $hash in the database
// Login
$input = $_POST['password'];
$stored_hash = $row['password']; // fetched from DB
if (crypt($input, $stored_hash) === $stored_hash) {
// login successful
} else {
// invalid credentials
}
?>While crypt works, it requires careful construction of the salt and algorithm identifier. Using password_hash is simpler and less error‑prone.
Conclusion
For secure password storage in PHP, avoid md5 and raw crypt. Prefer password_hash (bcrypt) together with password_verify, which automatically manages salts and provides strong resistance to attacks.
php Courses
php中文网's platform for the latest courses and technical articles, helping PHP learners advance quickly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
