Ever wonder what happens to your password after you hit “sign up“?
Or how a website can tell it’s you logging in without actually seeing your password?
If you’ve been searching for answers, this guide is here to clear all that up.
We’re going to walk you through the correct way to handle php password encryption. We’ll show you exactly how modern websites handle secure passwords with PHP, and we’ll give you a complete, hands-on mini-project to build your very own secure login system from scratch.
What is PHP Password Encryption?
PHP password encryption is the process of scrambling user passwords to protect them from unauthorized access. When a user creates an account, their password shouldn’t be saved as plain text.
Why?
Because if your database is ever compromised in a data breach, a hacker could instantly gain access to every single user’s password. This is a massive security risk that can lead to lawsuits, fines, and a complete loss of user trust.
Encryption is a fundamental part of web security that keeps your user data safe and your business protected.
Understanding Password Encryption vs. Hashing
When it comes to passwords, the terms “encryption” and “hashing” are often used interchangeably, but they are fundamentally different.
- Encryption is a two-way process. It involves a key to both scramble and unscramble data. This is great for sensitive data that needs to be reversible, like credit card numbers or secret messages.
- Hashing is a one-way process. You can create a hash from a password, but you can’t reverse it to get the original password back. For passwords, this is exactly what you want. You don’t need to know the user’s password; you just need to be able to verify that it’s correct.
This is why hashing is the preferred method for passwords. We use a password hashing algorithm to create a unique, irreversible string that represents the password.
Using password_hash()
This is the primary function for creating a secure password hash. It’s designed to be robust and future-proof.
Syntax:
string password_hash(string $password, int $algo, array $options = [])
The $algo parameter lets you choose a hashing algorithm. The best practice is to use PASSWORD_DEFAULT, which automatically selects the strongest, most up-to-date algorithm (currently Bcrypt). You can also specify PASSWORD_BCRYPT or PASSWORD_ARGON2ID for specific use cases.
Using password_verify()
This function securely checks a user’s password. It takes the plaintext password and the stored hash, and returns true if they match, or false if they don’t. It’s the only way to safely verify a password.
Example Code:
// Registration
$password = 'MySecurePassword123';
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
// Store $hashed_password in your database
// Login
$login_password = 'MySecurePassword123';
$stored_hash = '...'; // Retrieved from database
if (password_verify($login_password, $stored_hash)) {
echo 'Login successful!';
} else {
echo 'Invalid password.';
}
Hands-on Project: Building a Secure PHP Login System
Now that we’ve covered the theory, let’s put it all into practice. We’ll build a complete, secure PHP login system in two parts, starting with the core concepts and then connecting to a real database to make it a professional, real-world application.
For this project, I’ll assume you have a basic development environment set up with PHP and Composer.
Prerequisites
Before we start, you need to make sure your PHP environment is ready. We’ll be using Composer to manage our project’s dependencies, which is a modern best practice.
- Open your Command Prompt (CMD).
- Navigate to your XAMPP htdocs folder. This is where your websites live. You can usually get there with a command like:
cd C:\xampp\htdocs
- Create a new project folder. Let’s call it secure_login.
cd secure_login
- Now, you’re inside our project directory. All our files will go here.

Step 1: Launch XAMPP and Start Apache
First, you need to turn on your web server. Without it, your computer can’t “serve” the PHP file to your browser, which is why you saw nothing.
- Find and open the XAMPP Control Panel on your computer.
- Look for the Apache module and click the Start button next to it.
- Once it’s running, the name “Apache” and the port numbers will turn green. This means your localhost is now active.

Now that the server is on, your browser will be able to access the files in your htdocs folder.
Step 2: Setting Up the Project
For a secure password handling project, we don’t need any complex libraries. We’ll stick to core PHP functions, but it’s good practice to get used to a basic project structure.
Inside your secure_login folder, create two PHP files:
- register.php: This file will handle taking a user’s password, hashing it, and pretending to save it to a database.
- login.php: This file will take a user’s password input and verify it against the saved hash.

Step 3: Hashing a Password
Let’s work on the register.php file first. This is where we learn the golden rule: never store passwords in plain text. We’ll use the super-secure password_hash() function.
Think of hashing like a one-way street. You can easily go from a password to a hash, but you can’t go back from the hash to the original password. This is what makes it so secure!
Here’s the code for our register.php. I’ve added comments to explain each step.
<?php // A user's password, submitted from a registration form $unencrypted_password = "Cloudways@123"; // Hashing the password using the best available algorithm // PASSWORD_DEFAULT ensures our code stays up-to-date with PHP's latest recommendations. // This function automatically adds a unique "salt" to make the hash even more secure. $hashed_password = password_hash($unencrypted_password, PASSWORD_DEFAULT); // In a real application, you would now save this $hashed_password to your database. // For this mini-project, we'll just print it out. echo "Original Password: " . $unencrypted_password . "<br>"; echo "Hashed Password: " . $hashed_password . "<br>"; // We can even see what algorithm and cost were used. echo "Hash Info: "; print_r(password_get_info($hashed_password)); ?>

Open your browser and navigate to http://localhost/secure_login/register.php. You’ll see the original password alongside its long, random-looking hash. This is the value we’d store in our database.

Step 3: Verifying a Password (without Decrypting)
Now let’s build login.php. This file simulates a user trying to log in. This is where we use password_verify() to check if the password they entered matches the hash we have stored. Remember, we are verifying, not decrypting.
Here’s the code for login.php.
<?php
// The password a user entered in the login form
$user_input_password = "Cloudways@123";
// This would be the hash you retrieve from your database
// For this example, I'm just pasting the hash we generated from register.php
$stored_hash = '$2y$10$LZExuh/rXamd/X5yuDatn.L8ROlKBry3xidvWc.O19nx85.CrSrO.';
// Now we use password_verify() to check if the user's password
// matches our stored hash. It returns true or false.
if (password_verify($user_input_password, $stored_hash)) {
echo "Password is correct! User logged in successfully.";
} else {
echo "Incorrect password. Please try again.";
}
?>

Open your browser and navigate to http://localhost/secure_login/login.php. Because the passwords match, you’ll see a success message.

Now, try changing the value of $user_input_password to something else like “Cloudways@456“. Save the file, refresh your browser, and you’ll see the “Incorrect password” message.

And just like that, you’ve implemented a modern, secure password handling system in PHP. You’re now a step closer to making your blog a hub for security best practices!
Part 2: Building a Realistic Login System with a Database
Our first project was great for learning the core concept, but a real website doesn’t use hard-coded variables. It stores and retrieves user data from a database. In this part, we’ll connect our project to a MySQL database, which comes with your XAMPP installation.
For this next step, I’ll assume you have MySQL running in your XAMPP Control Panel.
Create a file called setup.php and add the following code.

This script will automatically create a database and a table for your users, so you don’t have to do it manually in phpMyAdmin.
<?php
// Database connection details
$servername = "localhost";
$db_username = "root";
$db_password = "";
// Create a new database connection
$conn = new mysqli($servername, $db_username, $db_password);
// Check for connection errors
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// SQL to create a new database
$sql_create_db = "CREATE DATABASE IF NOT EXISTS secure_blog";
if ($conn->query($sql_create_db) === TRUE) {
echo "Database 'secure_blog' created successfully or already exists.<br>";
} else {
echo "Error creating database: " . $conn->error . "<br>";
}
// Select the new database for use
$conn->select_db("secure_blog");
// SQL to create the users table
$sql_create_table = "CREATE TABLE IF NOT EXISTS users (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
password VARCHAR(255) NOT NULL
)";
if ($conn->query($sql_create_table) === TRUE) {
echo "Table 'users' created successfully or already exists.<br>";
} else {
echo "Error creating table: " . $conn->error . "<br>";
}
$conn->close();
?>
Now, all you have to do is open your browser and go to http://localhost/secure_login/setup.php to run this script. Once you see the “successfully created” message, you’re all set!

You can check phpMyAdmin to see the database and table created for you.

Step 1: The New register.php
Now, let’s update our register.php file to save the username and hashed password to our new database. We’ll use PHP’s mysqli extension to connect to the database.
<?php
// 1. Database Connection
$servername = "localhost";
$db_username = "root";
$db_password = "";
$dbname = "secure_blog";
// Create a new database connection
$conn = new mysqli($servername, $db_username, $db_password, $dbname);
// Check for connection errors
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// 2. User Data (from a form, in a real scenario)
$username = "CloudwaysUser";
$unencrypted_password = "Cloudways@123";
// 3. Hash the password
$hashed_password = password_hash($unencrypted_password, PASSWORD_DEFAULT);
// 4. Insert data into the database
$sql = "INSERT INTO users (username, password) VALUES (?, ?)";
// Use a prepared statement to prevent SQL injection
$stmt = $conn->prepare($sql);
$stmt->bind_param("ss", $username, $hashed_password);
if ($stmt->execute()) {
echo "User registered successfully! Hash stored in the database.";
} else {
echo "Error: " . $stmt->error;
}
$stmt->close();
$conn->close();
?>
Run this file in your browser by going to http://localhost/secure_login/register.php. You won’t see the hash on the screen, but if you go back to phpMyAdmin and browse the users table, you’ll see a new row with the username and the corresponding hash.
That hash is now saved, and it won’t change unless you run this script again.

Step 2: The New login.php
This is where the magic happens. Our login.php file will now be dynamic. It will retrieve the correct hash from the database to perform the verification, just like a real website. No more manual copy-and-paste!
<?php
// 1. Database Connection
$servername = "localhost";
$db_username = "root";
$db_password = "";
$dbname = "secure_blog";
$conn = new mysqli($servername, $db_username, $db_password, $dbname);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// 2. User Input (from a login form)
$username = "CloudwaysUser";
$user_input_password = "Cloudways@123";
// 3. Retrieve the stored hash from the database
$sql = "SELECT password FROM users WHERE username = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $username);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
$user = $result->fetch_assoc();
$stored_hash = $user['password'];
// 4. Verify the password
if (password_verify($user_input_password, $stored_hash)) {
echo "Login successful! Welcome, " . $username . ".";
} else {
echo "Incorrect password.";
}
} else {
echo "User not found.";
}
$stmt->close();
$conn->close();
?>
When you run the login.php page, the output depends on whether the hard-coded password matches the one stored in your database.
If the passwords match, you will see a success message: Login successful! Welcome, CloudwaysUser.

The script automatically performs this check by retrieving the user’s secure hash from your secure_blog database and comparing it to the password in the code.
Now, try changing the $user_input_password variable in the login.php file to something incorrect and run the script again. The system will correctly deny the login, just like a real website. You will see a failure message: Incorrect password.

This is what a modern, secure password system looks like. We’ve replaced the manual process with a database, making our project dynamic, realistic, and much more useful.
Best Practices for Password Hashing
- Always use strong hashing algorithms: Stick to PASSWORD_DEFAULT. It ensures your system is using the most current and robust algorithm available in your version of PHP.
- Let PHP handle salting: You don’t need to create your own salt. password_hash() automatically generates a unique, random salt for every password, which is essential for security.
- Consider a “pepper” for extra security: A pepper is a site-wide secret key that is added to the password before it is hashed. Unlike a salt, the pepper is not stored with the hash. This provides an extra layer of protection if your database is breached.
- Use password_needs_rehash(): Over time, new hashing algorithms become available, or the old ones can be updated to be more secure. This function checks if a stored hash was created with the recommended algorithm and options. If not, you can rehash the password and update it in your database on the user’s next login.
Common Mistakes to Avoid
- Using weak or outdated algorithms: Never use old, broken hashing methods like MD5 or SHA1 for password storage.
- Rolling your own encryption or hashing methods: Don’t try to invent your own password security scheme. The built-in PHP functions are extensively tested and peer-reviewed.
- Storing passwords in plain text or reversible encryption: Always use a one-way hashing method. Never store the original password or use a method that can be decrypted.
- Failing to update old password hashes: A lack of a rehash policy can leave your users vulnerable if an old algorithm becomes insecure.
Conclusion
This wraps up our guide on PHP password encryption. In this blog, we looked at why hashing is the preferred method for securing user passwords, how to use the modern, built-in functions like password_hash() and password_verify(), and how to apply these concepts in a hands-on project with a database.
We also covered the best practices for building a secure system and the common mistakes to avoid.
By applying these principles, you can ensure your web application provides robust data protection and builds trust with your users.
If you have any questions, let me know in the comments.
Frequently Asked Questions
Q. What is the difference between password_hash() and password_encrypt() in PHP?
PHP doesn’t have a password_encrypt() function. password_hash() is the recommended way to hash passwords securely. It automatically salts passwords and supports strong algorithms like bcrypt and Argon2, making it much safer than manual encryption methods.
Q. Can I use PHP password hashing for existing plain-text passwords?
Yes. When migrating users from plain-text passwords, you can hash their passwords upon their next login or require a password reset. Always use password_hash() for new passwords and password_verify() to check them.
Q. How often should I update password hashing algorithms in PHP?
You should periodically check if your hashing algorithm is still considered secure. PHP’s password_needs_rehash() function can help identify outdated hashes so you can upgrade to a stronger algorithm without forcing users to change their passwords immediately.
Abdul Rehman
Abdul is a tech-savvy, coffee-fueled, and creatively driven marketer who loves keeping up with the latest software updates and tech gadgets. He's also a skilled technical writer who can explain complex concepts simply for a broad audience. Abdul enjoys sharing his knowledge of the Cloud industry through user manuals, documentation, and blog posts.