How to Securely Hash Passwords in PHP

Securing user passwords is a critical aspect of web development, and PHP makes this process straightforward with its built-in password hashing API. This article explains how to use the modern password_hash() and password_verify() functions to securely store and validate passwords, eliminating the need for outdated algorithms like MD5 or SHA1.

Hashing a Password with password_hash()

To secure a password before storing it in a database, use the password_hash() function. This function automatically handles the generation of a secure cryptographic salt and applies a strong one-way hashing algorithm (like bcrypt or Argon2).

Here is the standard way to hash a password:

$password = "user_secure_password123";

// Hash the password using the default recommended algorithm
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);

// Save $hashedPassword in your database (requires a VARCHAR column of at least 60 characters, though 255 is recommended)

The PASSWORD_DEFAULT constant tells PHP to use the strongest algorithm currently supported by default. As of PHP 8, this is bcrypt.

Verifying a Password with password_verify()

When a user attempts to log in, you must verify the plain-text password they entered against the hashed password stored in your database. You do this using password_verify().

$userInput = "user_secure_password123"; // Password from the login form
$storedHash = "..."; // Retrieve the hash previously stored in the database

if (password_verify($userInput, $storedHash)) {
    echo "Password is valid!";
    // Proceed to log the user in
} else {
    echo "Invalid password.";
}

This function is highly secure because it is resistant to timing attacks, which are common exploits used to guess passwords based on how long a server takes to process input.

Updating Hashes with password_needs_rehash()

Over time, PHP updates its default hashing algorithms or increases the default computational cost to keep up with faster hardware. To ensure older password hashes are updated automatically when users log in, use password_needs_rehash().

if (password_verify($userInput, $storedHash)) {
    // Check if the hash was created with an older algorithm or cost factor
    if (password_needs_rehash($storedHash, PASSWORD_DEFAULT)) {
        // Rehash the password and update the database
        $newHash = password_hash($userInput, PASSWORD_DEFAULT);
        // Save $newHash in the database for this user
    }
    // Proceed to log the user in
}

By combining these three functions, your PHP application will maintain industry-standard password security with minimal maintenance.