PHP - Encrypting Passwords

 

This lesson is part of an ongoing User Authentication tutorial. The first part is here: User Authentication along with all the files you need.

The first script to take a look at in your login folder is signup.php. You can fire up your server and try it out. What you'll see is a simple login page with textboxes for username and password, as well as a Register button. It will look like this:

The PHP signup page

Type a username and password, and make a note of the them, as you'll be needing these details for the login page.

Click the button to register, and you should see "item inserted" printed to the page:

A new user has signed up

Open up the signup.php script and take a look at the code. (It's one of the files you downloaded from here: scripts.) The HTML for this form can be seen at the bottom of the page. There's nothing special about it. But notice that there's a PHP print statement in the HTML Body section:

<?PHP print $errorMessage;?>

This is for displaying error messages for the user.

The first few line of the script, though, just set up some variables:

$uname = "";
$pword = "";
$errorMessage = "";

The next part of the code is where we check to see if the form has been POSTED or not (was the Register button clicked):

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
}

Next, we grab the username and password from the textboxes:

$uname = $_POST['username'];
$pword = $_POST['password'];

Then we attempt to connect to the database and server:

require '../../configure.php';
$database = "login";
$db_found = new mysqli(DB_SERVER, DB_USER, DB_PASS, $database );

We have two sets of dot/dot/slash now before require configure.php. This is because we created a folder for ourselves to hold the login scripts. The root folder (the www one) would be one folder up from this new folder. However, as stated in a previous tutorial, it's a bad idea to place your login credentials in the root folder. Our login credentials are outside of the root folder, hence the two sets of dot/dot/slash.

We then create a new mysqli object passing in all those constants we set up in the configure file. (SEE HERE, if you skipped this lesson.)

If the database was found, then the variable called $db_found will be true. We check for this in the next lines:

if ($db_found) {
}

else {

$errorMessage = "Error logging on";

}

If the database isn't found, then some text is added to the error message variable. If the database is found, then we set up a prepared statement:

$SQL = $db_found->prepare('SELECT * FROM login WHERE L1 = ?');

$SQL->bind_param('s', $uname);
$SQL->execute();

Notice the SQL in the first line:

SELECT * FROM login WHERE L1 = ?

We only want to select the L1 column, which is the username. We're going to make sure that this column is a unique value, meaning you can't have two people with the same username. To do that, we need to get the results from the SQL query:

$result = $SQL->get_result();

If any results are returned, then we know that the username is taken. So we can display a message:

if ($result->num_rows > 0) {

$errorMessage = "Username already taken";

}

If no results are returned, then we can go ahead and add the chosen username to the database.

else {

$phash = password_hash($pword, PASSWORD_DEFAULT);

$SQL = $db_found->prepare("INSERT INTO login (L1, L2) VALUES (?, ?)");
$SQL->bind_param('ss', $uname, $phash);
$SQL->execute();

print "item inserted";

}

The first line of this new code is where we set up the encryption:

$phash = password_hash($pword, PASSWORD_DEFAULT);

The PHP function password_hash is an inbuilt one. In between the round brackets of password_hash you need some text you want to encrypt. After a comma, you specify the encryption algorithm that you want to use. You can either use PASSWORD_DEFAULT or PASSWORD_BCRYPT here. These two are inbuilt constants. PASSWORD_DEFAULT gets you the bcrypt algorithm. It's recommended that you created a field in your database 255 characters long. Rather confusingly, PASSWORD_BCRYPT use the crypt_blowfish algorithm. For more information on these two algorithms see here:

http://php.net/manual/en/function.password-hash.php

Once password_hash has done its work, it will either return you a hashed (and salted) password, or it will return false, if something went wrong. (You could set up an if statement to test for this, if you wanted.)

Once we have a hashed password, we can setup another prepare statement:

$SQL = $db_found->prepare("INSERT INTO login (L1, L2) VALUES (?, ?)");
$SQL->bind_param('ss', $uname, $phash);
$SQL->execute();

header ("Location: login.php");

The SQL line is this:

INSERT INTO login (L1, L2) VALUES (?, ?)

So we're INSERT INTO with our two database table fields L1 and L2. The VALUES are question mark placeholders. The next line binds these parameters:

$SQL->bind_param('ss', $uname, $phash);

We then only need to execute and print something out:

$SQL->execute();
header ("Location: login.php");

The last line redirects the new user to the login page. If you took the user's email address you could also send them something to let them know they have been successful. But please don't email them their new password in plain text!

In the next lesson, we'll take a look at the login.php script.