How to Secure your Application in 5 Simple Steps

Manage passwords, hashing, and encryption in PHP

Nico Anastasio
11 min readSep 14, 2019

The 2012 Yahoo Voice hack;

Cambridge Analytica;

The 2016 US Democratic email leak;

The 2018 Google data breach.

These are only some of the data breaches that have affected us during the last decade or two.

The world’s information has been available to us like never before.

At the same time, if you haven’t been careful, your information (even more private) has traveled the opposite way.

As a web developer,

Does not matter what type of application you are developing.

You have the responsibility to ensure the security of all your platforms.

But, I don’t blame you.

Security is hard,

A good place to start is by using good practices when working with passwords.

PHP provides several tools and functions that we can use to make our application safe.

In this post, you are going to discover all you need to know to make your applications airtight.

3 rules for password security

Never know user passwords

I still remember my first days as a PHP developer, one of the first applications I created was a game to manage a fantasy football team with my friends.

Each of us could log in to our accounts, add players, and deploy the teams every week for the new game.

Treat your password like your toothbrush. Don’t let anybody else use it, and get a new one every six months.

Clifford Stoll

I remember also that I created their basic accounts,

I added usernames and passwords for them all and emailed them the credentials that needed to use.

Only months after I learned and realized how silly, and dangerous that was.

As a general rule:

Not only you should never know the password of your users, but you also should never be able to know them.

This is a serious matter.

It can imply lots and lots of legal liabilities.

As a rule of thumb, you do not want to store passwords in plain text or use decryptable passwords.

Do not restrict passwords

Let’s play a game,

Guess the following password:

**********

Hard isn’t it?

Let’s try again:

P*r***e***

Now you know that there are capital letters and a few more lowercase letters in the middle

How about numbers?

P*r*che911

Now that you know that the word includes a capital letter, lowercase letters, and a number it is so much easier to guess.

The same happens when restricting the choices our users have about their passwords.

If one of your application’s requirements is to follow a definite pattern you are providing hints that malicious users can use against you.

Despite what you might think it is ok to use a small number of characters.

you don’t need a 30 letters-long password.

But, the length of a password affects the time spent finding it out.

It is much better to learn how algorithms and hashing work

Photo by Towfiqu barbhuiya on Unsplash

Never email passwords in clear

As I wrote in my little story above, one of my first errors as a web developer was not learning how to manage passwords earlier.

This was before I came across good practices.

I was (and still am) figuring this programming thing out.

In Modern PHP, Josh Lockhart wrote about this issue.

He illustrates how developers can lose trust in a matter of seconds.

Imagine you are a client and hire a web developer for creating a nice and shining e-commerce website for your business,

Now,

You receive an email from your developer and the email contains a password for your website.

This a simple example but keep following along…

You now learned 3 things about your pal,

  1. He knows your password;
  2. He is storing your password in clear with little to no encryption at all;
  3. He cannot care less about sending passwords over the internet;

The next letter you should send him should be a Notice of Termination.

Here is what you as a web developer should do.

Create a page on your web application that allows inserting the user’s email when he/she forgot its password to request a new one.

Your application now generates a unique token and associates the token with the user that made the request (I use UUID on this occasion).

Your application then sends an email to the user with a link that includes the token.

Once the user visits the URL, your application validates the token and allows the user to change their password.

After the password is changed, the token is deleted.

How much has the security of the application increased with these simple steps?

This is what is called good practice.

We can even higher the level of security by adding a time limit between the request of the new password and the submission of the new one if we want.

How to hash users’ password

Let’s start with an explanation.

You should hash the password of your web application, you do not encrypt them.

That made me struggle for a while.

The difference between the two is that encryption is a 2-way algorithm.

You encrypt a string then you can decrypt and get your string back.

This is used in intelligence when sending or receiving messages by allies.

Hashing is something different, a hashed string cannot go back to plain text, or at least this is the final goal.

There are many algorithms designed for different purposes, some need to be fast, and others very secure.

This is an always-changing technology, with a lot of improvement in the last few years.

We are going to have a look at three of the most popular in chronological order.

Sha-1

This is the first hashing function.

SHA1 stands for Secure Hashing Algorithm, and it was developed by the NSA.

It was very famous and one of the most used in the PHP world in producing a 20-byte hexadecimal string, 40 digits long.

The SSL industry has chosen SHA1 for digital signatures for several years.

Then, Google decided that was time to upgrade to SHA-2.

The first version of this algorithm has been “deprecated” in 2005.

Designs of new versions (SHA-2, SHA-3, and SHA-256) are now used.

Bcrypt

Bcrypt is not the natural evolution from the SHAs but is the one that picked up more audience for his security.

It has been designed to be slow and produce the most secure hashing string possible.

It does several iterations that hash the data, in technical terms that’s called work factor,

The higher the work factor the more expensive would be for a hacker to get the password.

The good news is that in the future when we are going to have more powerful machines we can do more iterations.

I will leave an amazing link regarding Bcrypt by the guy at auth0.

Argon2

This is the brand-new shining thing in the world of hashing.

Alex Biryukov, Daniel Dinu, and Dmitry Khovratovich designed it.

It won the Password Hashing Competition in 2015.

Argon2 is divided into 3 versions:

  • Argon2d;
  • Argon2i;
  • Argon2id;

Argon2d accesses the memory array.

It reduces the possibility of time-memory trade-off but it has a possible side-channel attack.

Argon2i is quite the opposite.

Optimized for side-channel attacks and accesses the memory in a password-independent order.

Argon2id consists of a mix of the two versions.

This function has 6 parameters.

The string of the password, the salt, the memory cost, the time cost, the parallelism factor, and the length of the hash.

The parallelism factor is the greatest number of parallel threads allowed.

You will see below how to use this hash in PHP leveraging built-in functions.

Also, I have already written about this hashing almost a year ago when PHP 7.3 was released.

Hashing and Verify a password in PHP 7

Hashing the password with password_hash

This function creates a password hash according to the parameters we decide to pass to it.

It uses a one-way algorithm.

We can decide which type of algorithm we want to use by inserting the constant of our choice, the constants available are:

  • PASSWORD_DEFAULT from PHP 5.5 uses the Bcrypt algorithm as a default algorithm. It changes over time according to the discovery of a new and more secure algorithm, or other factors.
  • PASSWORD_BCRYPT produces a crypt() hash. It is 60 characters long and you can recognize it by its identifier that looks like this $2y$
  • PASSWORD-ARGON2I Argon2 is one of the most secure hashes available at the moment. Available only if your PHP has been compiled with Argon2
  • PASSWORD_ARGON2ID It uses the Argon2ID version rather than the I.

This function has also an optional parameter consisting of an associative array.

It accepts several keys according to the algorithm we choose to use.

In case you prefer to use Bcrypt the key of this array will be the cost (an integer representing an expansion iteration count as a power of two).

If you choose to use the algorithm that uses Argon2 there will be different keys.

They are going to be:

  • memory_cost (an integer that indicated the largest memory needed to be used to compute the hash);
  • time_cost (an integer that indicates the longest time is going to be needed to compute the hash);
  • thread (another integer that specifies the number of threads to use when computing the hash).

Do not provide the salt in PHP 7.0, doing so is going to produce a deprecation warning.

Now that we know all the elements required to use the password_hash() function let’s see how to write it.

It is recommended that you test this function on your servers.

You need to adjust the cost parameter so that the execution of the function takes less than 100 milliseconds on interactive systems.

The script in the above example will help you choose a good cost value for your hardware.

Also, have a look at what the official manual has to say about password_hash

For the first time, individual hackers could afford to have home machines comparable in power and storage capacity to the minicomputers of ten years earlier — Unix engines capable of supporting a full development environment and talking to the Internet.

Eric S. Raymond

Verify the user’s password

You have allowed users to register for your brand-new application.

They can insert their password and you know how to handle them.

Hashing them according to the last security trends.

You do not store anything in clear and your server is hidden inside a vault 10 meters underground.

Great job!

Now what?

Now you need to allow the user to log in to your application.

To do that PHP provides a built-in function that verifies that the password matches the hashed string.

This function is called password_verify().

It has two parameters.

Both must be of type string.

The first parameter is the password the user has typed into the login form.

It has to be a plain text password, and the second parameter is the actual hash we need to verify against.

The result is a boolean value that we can use inside the conditional operation and log the user in or tell him something goes wrong.

Here is an example:

Something to notice is that you cannot use double quotes when using the $hash string.

As you can see there are several dollar signs inside the variable.

They will be evaluated rather than parsed.

The official manual has a page about password_verify as well.

How to Create a User Registration system in PHP

I hope you now understand how PHP developers manage security practices.

If you still have any doubts ask your questions on our community.

We have seen how these built-in functions work in theory, now we are going to see how to use them when creating a basic signup and login system.

1. Create a database table using a SQL language

CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`email` varchar(50) NOT NULL,
`password` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
);

This code above is not PHP but MySql and will create a table called users in which we are going to store the users’ data we need.

Database language and queries are out of the scope of this tutorial, if what you have seen confused you have a look at this tutorial about MySQL

2. Create a Signup or Registration form signup.php

<form action="signup.php" method="POST" >
<input name="username" required="" type="text" />
<input name="email" required="" type="text" />
<input name="password" required="" type="password" />
<input name="submit" type="submit" value="Register" />
</form >

The code above represents a very basic HTML form that sends a post request to the page signup.php.

All the fields within the post are required.

The goal is to send and elaborate the information provided within the form to register and log the user in.

3. Register the user

The snipped above gathers all the information submitted by the user.

It also has the password using PASSWORD_DEFAULT as the algorithm of choice (BCrypt is built-in in PHP7).

Now we prepare and execute a statement in which we check if the user already exists in our database and if not we insert his data.

There are several expedients we can use to make this code much more secure.

Have a look at the first episode of this series about Good Practices — Input validation

4. Create the login form

<form action="login.php" method="POST">
<input name="username" required="" type="text" />
<input name="password" required="" type="password" />
<input name="login" type="submit" value="Login" />
</form>

Another very simple form.

After the user has filled in the field and submitted the form we will send a post request to the login.php page.

then we will check the data and grant access to the user.

5. Allow the user to access the web application

Here you see the function password_verify() in action.

The first thing we check is if the page has a post request, then select and count the number of users that match the input submitted.

If everything went well, this number should be 1,

We now verify the password and redirect the user to the home page.

Otherwise, we need a little bit of help from Javascript to show an alert box with an error message.

Tap on the image to subscribe and be the first to get all the new posts

Click to subscribe and be the first to get all the new posts

Conclusion

You have learned how to keep your web application safe and manage your password.

Remember that following good practices is not a list of a standard that you need to follow, it is a path that you should enjoy.

Doing it daily learning new techniques and experimenting with your code will make you a black belt in coding.

Whether you are using PHP or prefer to discover what other languages have to offer.

--

--

Nico Anastasio

Experienced programmer empowering developers to write flawless code. Explore my blog: anastasionico.uk/blog. Need captivating articles? nico@anastasionico.uk.