Web Security
Beginner
1 min read
Secure Password Storage with bcrypt and Argon2
Example
<?php
// Secure password hashing with PHP password_hash()
// --- REGISTRATION: hash the password before storing ---
$plainPassword = $_POST['password']; // e.g., "correct-horse-battery-staple"
// Argon2id (preferred for new applications, PHP 7.3+)
$hashedArgon2 = password_hash($plainPassword, PASSWORD_ARGON2ID, [
'memory_cost' => 65536, // 64 MB
'time_cost' => 4, // 4 iterations
'threads' => 2,
]);
// bcrypt (widely supported, excellent default)
$hashedBcrypt = password_hash($plainPassword, PASSWORD_BCRYPT, ['cost' => 12]);
// Store $hashedArgon2 or $hashedBcrypt in the database — never $plainPassword
// --- LOGIN: verify and rehash if needed ---
$storedHash = fetchHashFromDb($username); // from database
if (password_verify($plainPassword, $storedHash)) {
// Authentication succeeded
// Upgrade hash if algorithm or cost factor changed
if (password_needs_rehash($storedHash, PASSWORD_ARGON2ID, [
'memory_cost' => 65536,
'time_cost' => 4,
'threads' => 2,
])) {
$newHash = password_hash($plainPassword, PASSWORD_ARGON2ID, [
'memory_cost' => 65536,
'time_cost' => 4,
'threads' => 2,
]);
updateHashInDb($username, $newHash); // transparent upgrade
}
startUserSession($username);
} else {
// Use a generic error — never reveal whether username or password was wrong
throw new AuthenticationException('Invalid credentials.');
}
Related Resources
Web Security Reference
Complete tag & property list
Web Security How-To Guides
Step-by-step practical guides
Web Security Exercises
Practice what you've learned
More in Web Security