Password Hashing and Authentication

Table of Contents

  • Introduction to Password Hashing
  • Why Hashing is Important
  • Using PHP’s Built-in Hashing Functions
  • Salting: Adding Extra Security
  • Best Practices for Password Hashing
  • Implementing Authentication with Password Hashing
  • Two-Factor Authentication (2FA)
  • Using Modern Authentication Libraries
  • Conclusion

Introduction to Password Hashing

In web applications, authentication is one of the most crucial aspects of security. One of the primary concerns is how to securely store user passwords. Storing plain-text passwords in your database is an enormous security risk—if your database is compromised, all user passwords are exposed.

Password hashing is the process of converting a password into a fixed-length string of characters that appears to be random. This transformation is one-way, meaning you cannot recover the original password from the hash. By using secure hashing algorithms, you can make it almost impossible for attackers to reverse-engineer passwords, even if they have access to the hashed values.

In this module, we will dive deep into password hashing techniques in PHP and discuss best practices for authentication.


Why Hashing is Important

Password hashing serves multiple purposes:

  1. Security: It prevents storing sensitive data (like passwords) in plaintext.
  2. Irreversibility: Hashing is a one-way function, so even if someone steals the hash, they cannot reverse it to obtain the original password.
  3. Salted Hashes: Hashing allows the use of salts, which adds an additional layer of uniqueness and security to the hashed password.

However, a hashed password by itself is not enough. A secure authentication mechanism, such as using salts and modern hashing algorithms, ensures that even if attackers gain access to your hashed passwords, they cannot easily crack them.


Using PHP’s Built-in Hashing Functions

PHP provides powerful functions for hashing passwords securely, the most notable being password_hash() and password_verify(). These functions are part of PHP’s Password Hashing API (introduced in PHP 5.5) and handle password hashing and verification in a secure and easy-to-use manner.

password_hash()

This function is used to create a secure password hash. It uses the bcrypt algorithm by default (though you can specify other algorithms).

  • Creating a Password Hash:
phpCopyEdit<?php
$password = 'userPassword123';
$hash = password_hash($password, PASSWORD_DEFAULT);

echo "Hashed Password: " . $hash;
?>
  • PASSWORD_DEFAULT is the algorithm that will always use the strongest available hashing method (currently bcrypt).

Important: You should always use password_hash() to generate the hash instead of using cryptographic libraries manually, as this ensures that you are using a safe algorithm and handling salts automatically.

password_verify()

This function is used to verify that a given password matches a stored hash. It compares the entered password with the stored hash in a secure way.

  • Verifying a Password:
phpCopyEdit<?php
$enteredPassword = 'userPassword123'; // Password entered by user
$storedHash = '$2y$10$T4t7ajUyDdXy7JdD9D0mDeS/mFdp7Pz9GVVfhsFrTXJwveFs/.0zG'; // Hash stored in DB

if (password_verify($enteredPassword, $storedHash)) {
    echo "Password is correct!";
} else {
    echo "Incorrect password!";
}
?>

If the entered password matches the stored hash, password_verify() returns true; otherwise, it returns false.


Salting: Adding Extra Security

Salting is the process of adding a random value (a “salt”) to the password before hashing it. Salts ensure that even if two users have the same password, their stored password hashes will be different, because each password is hashed with a unique salt.

PHP’s password_hash() automatically generates a salt and includes it in the resulting hash, so you don’t have to manually add one. This makes password_hash() a robust solution for password security.

  • Why Salting is Important:
    • Unique Hashes for Identical Passwords: Without salts, two users with the same password would have identical hashes. With salting, even if two users choose the same password, the hashes will be different due to the unique salt.
    • Protection from Rainbow Table Attacks: A rainbow table is a precomputed table used to reverse cryptographic hash functions. Salting ensures that attackers cannot use precomputed tables to crack passwords quickly.

Best Practices for Password Hashing

To ensure that your password hashing is secure, follow these best practices:

  1. Always Use Strong Hashing Algorithms: Use bcrypt (via PASSWORD_DEFAULT in PHP) or argon2 (via PASSWORD_ARGON2I or PASSWORD_ARGON2ID) for hashing passwords. These algorithms are designed to be slow and resistant to brute-force attacks.
  2. Never Store Plaintext Passwords: Always hash and salt passwords before storing them in your database.
  3. Use password_hash() and password_verify(): These functions are designed to handle hashing securely and efficiently. Don’t roll your own hashing functions.
  4. Adjust Hashing Cost Factor: For bcrypt, you can adjust the cost factor (difficulty) to make the hashing process slower and more resistant to brute-force attacks. A higher cost factor increases security but also increases computational time. phpCopyEdit$options = [ 'cost' => 12, // Cost factor ]; $hash = password_hash($password, PASSWORD_BCRYPT, $options); The default cost is 10, and it is recommended to keep it around 12 for a good balance of security and performance.
  5. Rehash Passwords Periodically: If you change your hashing algorithm or adjust the cost factor, it’s essential to rehash stored passwords. You can check if the hash needs to be rehashed with password_needs_rehash(). phpCopyEditif (password_needs_rehash($storedHash, PASSWORD_BCRYPT, $options)) { // Rehash password $newHash = password_hash($password, PASSWORD_BCRYPT, $options); // Store the new hash }

Implementing Authentication with Password Hashing

Now that we know how to hash and verify passwords securely, let’s implement a basic login authentication system.

User Registration:

phpCopyEdit<?php
// User registration logic
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = $_POST['username'];
    $password = $_POST['password']; // Plaintext password entered by user

    // Hash the password
    $hashedPassword = password_hash($password, PASSWORD_DEFAULT);

    // Store username and hashed password in the database
    $query = "INSERT INTO users (username, password) VALUES ('$username', '$hashedPassword')";
    // Execute query to store in DB (ensure proper escaping and security)
}
?>

User Login:

phpCopyEdit<?php
// User login logic
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = $_POST['username'];
    $password = $_POST['password'];

    // Fetch stored hash from the database
    $query = "SELECT password FROM users WHERE username = '$username'";
    $storedHash = fetchPasswordFromDatabase($query); // Assume this function retrieves the stored password hash

    if (password_verify($password, $storedHash)) {
        echo "Login successful!";
    } else {
        echo "Invalid credentials!";
    }
}
?>

Two-Factor Authentication (2FA)

While password hashing is crucial, two-factor authentication (2FA) adds an additional layer of security. With 2FA, even if a user’s password is compromised, an attacker would also need access to the second factor (such as a code sent via SMS or generated by an authenticator app).

You can implement 2FA using third-party libraries like Google Authenticator or Authy. These libraries generate time-based one-time passwords (TOTP) that change every 30 seconds.


Using Modern Authentication Libraries

PHP has several modern libraries that simplify the process of implementing authentication, including password hashing and two-factor authentication. Some popular libraries include:

  • PHP-JWT: A library for creating and validating JSON Web Tokens (JWTs), often used for stateless authentication in APIs.
  • OAuth2 Server: A library to implement OAuth 2.0 authentication for your API.
  • Google Authenticator: For integrating two-factor authentication (2FA) with your PHP application.

Conclusion

In this module, we have covered essential aspects of password hashing and authentication, including:

  • Why password hashing is necessary for secure authentication.
  • Using PHP’s built-in functions (password_hash() and password_verify()) to securely handle passwords.
  • Best practices for salting, password storage, and cost factors.
  • Implementing a basic authentication system with password hashing.
  • Enhancing security with two-factor authentication (2FA).
  • Leveraging modern authentication libraries and techniques.

By following these best practices and integrating secure authentication methods, you can ensure your PHP applications are well-protected against common security threats.