PHP MySQL password hashing


In PHP MySQL procedural style, using password_hash() is essential for securely storing passwords in the database. This function provides a strong one-way encryption that makes it virtually impossible to reverse the hashed password into its original form, ensuring the security of stored passwords.

What is password_hash()?

password_hash() is a built-in PHP function that hashes passwords using strong and secure algorithms. By default, it uses the Bcrypt algorithm, but newer versions of PHP support Argon2 as well.

Key features:

  • Automatically generates a salt (random data added to the password before hashing).
  • Uses a cost factor, which defines the computational complexity of the hashing algorithm.
  • Compatible with password_verify() to check if a given password matches the stored hash.

How password_hash() Works

  1. Hashing the password: Convert the plain-text password into a hashed string before saving it to the database.
  2. Verifying the password: When a user logs in, the plain-text password they provide is compared against the hashed password stored in the database using password_verify().

Syntax of password_hash()

password_hash(string $password, int $algo, array $options = [])
  • $password: The plain-text password to be hashed.
  • $algo: The algorithm used (e.g., PASSWORD_DEFAULT, PASSWORD_BCRYPT).
  • $options: An optional array of options like cost (higher cost makes it harder to brute-force but slower to compute).

Example: Registering a User with password_hash()

Let’s create a simple example of how to hash passwords using password_hash() and store them in a MySQL database.

Step 1: Create the Registration Form

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>User Registration</title> </head> <body> <h2>User Registration</h2> <form action="register.php" method="POST"> <label for="username">Username:</label> <input type="text" id="username" name="username" required><br><br> <label for="email">Email:</label> <input type="email" id="email" name="email" required><br><br> <label for="password">Password:</label> <input type="password" id="password" name="password" required><br><br> <input type="submit" value="Register"> </form> </body> </html>

Step 2: PHP Code to Handle Registration and Hash the Password (register.php)

<?php // Check if the form was submitted if ($_SERVER['REQUEST_METHOD'] == 'POST') { // Step 1: Capture the input data and sanitize $username = trim($_POST['username']); $email = trim($_POST['email']); $password = trim($_POST['password']); $username = filter_var($username, FILTER_SANITIZE_STRING); $email = filter_var($email, FILTER_SANITIZE_EMAIL); // Step 2: Validate input data if (empty($username) || empty($email) || empty($password)) { die("All fields are required."); } if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { die("Invalid email format."); } // Step 3: Hash the password $hashed_password = password_hash($password, PASSWORD_DEFAULT); // Step 4: Connect to MySQL $conn = mysqli_connect("localhost", "root", "", "test_db"); // Check the connection if (!$conn) { die("Connection failed: " . mysqli_connect_error()); } // Step 5: Prepare the SQL query $sql = "INSERT INTO users (username, email, password) VALUES ('$username', '$email', '$hashed_password')"; // Step 6: Execute the query and insert data if (mysqli_query($conn, $sql)) { echo "User registered successfully!"; } else { echo "Error: " . $sql . "<br>" . mysqli_error($conn); } // Close the connection mysqli_close($conn); } ?>

Step-by-Step Breakdown:

  1. User Inputs:

    • The form collects the username, email, and password.
    • PHP retrieves the inputs using the $_POST superglobal and sanitizes them using filter_var().
  2. Hash the Password:

    • The password entered by the user is hashed using password_hash($password, PASSWORD_DEFAULT).
    • The PASSWORD_DEFAULT constant ensures that PHP uses the best available hashing algorithm (currently Bcrypt).
    • The hashed password is a long string that contains both the salt and the hashed password.
  3. Insert the User Data:

    • The hashed password, along with the username and email, is inserted into the MySQL database.
    • The password is stored as a hashed value, ensuring that even if the database is compromised, the passwords remain secure.

Step 3: Create the Database Table

Create a users table in MySQL to store user registration information.

CREATE DATABASE test_db; USE test_db; CREATE TABLE users ( id INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL, email VARCHAR(50) NOT NULL, password VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );

Verifying the Password During Login

When a user logs in, you'll need to verify the entered password against the stored hashed password. This is done using the password_verify() function.

Example: Login Script (login.php)

<?php if ($_SERVER['REQUEST_METHOD'] == 'POST') { $email = trim($_POST['email']); $password = trim($_POST['password']); // Sanitize email $email = filter_var($email, FILTER_SANITIZE_EMAIL); // Connect to MySQL $conn = mysqli_connect("localhost", "root", "", "test_db"); if (!$conn) { die("Connection failed: " . mysqli_connect_error()); } // Retrieve the stored hashed password for the user $sql = "SELECT * FROM users WHERE email = '$email'"; $result = mysqli_query($conn, $sql); if (mysqli_num_rows($result) == 1) { $user = mysqli_fetch_assoc($result); $hashed_password = $user['password']; // Step 1: Verify the entered password against the stored hashed password if (password_verify($password, $hashed_password)) { echo "Login successful!"; // Start a session or redirect the user } else { echo "Invalid password."; } } else { echo "User not found."; } mysqli_close($conn); } ?>

Password Verification:

  1. Retrieve User: The script retrieves the user’s record from the database based on the provided email.
  2. Verify Password: The password_verify($password, $hashed_password) function checks if the entered plain-text password matches the hashed password stored in the database.
  3. Handle Result: If the password is correct, the user is logged in. If not, an error message is displayed.

Benefits of password_hash() and password_verify():

  1. Automatic Salting: password_hash() generates a random salt automatically, making the same password produce a different hash each time.
  2. Strong Hashing: The default algorithm (PASSWORD_DEFAULT, currently Bcrypt) is designed to be slow to defend against brute-force attacks.
  3. Future-proof: The PASSWORD_DEFAULT constant automatically upgrades to stronger algorithms as they become available in future PHP versions, without needing to modify your code.