laravel passwords security

Programmers, don't store users' passwords!

Written on 19th May 2019
It will take between 4 and 5 minutes to read this article

It is quite likely if you've been using the internet for a few years, you've forgotten your password. Now most 'forgot your password' functions will send you a link to your email for you to create a new password. However, there are some which say "Your password is: FreddyLovesAvocado92". If this happens then there is only one way they can be sending you that information. They are storing your password, and what is worse it's almost certainly going to be in plain text.

Why is storing a password in plaintext bad?

Many users use the same password on different sites so if your database is hacked, a hacker could try those email/password combinations on other sites.

Even as a beginner

Please, for the love of all that is good, as a developer or programmer, please do not store your users' passwords in plain text. Even if you're beginning out in this field, please learn about hashing passwords. It's relatively simple and will be far more secure.

So what can we do?

So we know we cannot store a user's password in the database in plain text, but what options do we have open to us? We might consider encyption for the task, however what can be encrypted can be unencrypted, so although it is harder than had the password been stored in plain text, if the hacker also steals encryption key(s), the password might as well be in plain text. So what we're looking for is something that can be 'encrypted' but not 'decrypted' which is where Hashing comes into play.

Hashing

Hashing is a process of transforming a string of characters into another value. Usually represented by a shorter, fixed-length value. A hash function generates new values according to a mathematical hashing algorithm, known as a hash value or simply a hash. To prevent the conversion of hash back into the original key, a good hash always uses a one-way hashing algorithm. 1

So in our application we will use a hashing function in order to encrypt the user's password but we will be unable to decrypt it. To get our hash we will use a hash function. A hash function maps data of any length using a one-way mathematical algorithm to output a string of a fixed size.

There are two main hashing functions at currently

For example: FreddyLovesAvocado92 (20 chars) when hashed might become $2a$10$CvQ7N/a1mYsmkB4RDhL0o.mE05MYJAwcIjYXTSFQt/Nt0qKzR3z2m (60 chars). Now no matter how long the password is it will always be 60 characters when hashed in this case. So supercalafragalisticexpialadocious (40 chars) will become $2a$10$IidG7wJhjag2KZkd6YVV.eOM0os/GXzFOJOhRGwHSyL2tI/mUpf7G (60 chars).

So how might we achieve this in PHP and Larvel? Laravel has a handy function called bcrypt but this is only available in Laravel.

<?php
 
// in pure php
password_hash('my secret password', PASSWORD_BCRYPT, ['cost' => 12]);
 
// in laravel
bcrypt('my secret password');
 
// outputs: $2y$10$GunPTYLUgw6.ZFH1EtH1cOckgPQQBJcE88XxCOKFI1TgJ2DkBLe22

Now, something you need to realise with hashing is that the it doesn't return the same result twice. So, FreddyLovesAvocado92 won't always be $2a$10$CvQ7N/a1mYsmkB4RDhL0o.mE05MYJAwcIjYXTSFQt/Nt0qKzR3z2m, so we can't just check to see if the password the user is trying to log in with is directly equal to the one we have stored in the database. However PHP comes with a useful function called password_verify in which we can check to see if what the user is giving us as their password is correct or not.

<?php
 
// let's grab our user's password
$userPassword = $_POST['password'];
 
if (password_verify($userPassword, hashedPasswordStoredInDb()) {
// the user's password was correct
// log them in ...
} else {
// the user's password was incorrect
// show them an error message ...
}

Salting

Salting is the process of adding unique random strings of characters to passwords in a database or each password before the password is hashed. This is done to change the hash and make passwords more secure. The string of characters added to the password is called the salt. A salt can be added in front or behind a password. 2

One really good thing about bcrypt is it has an internal salting mechanism. We don't really need to add salting to a string which is going to be bcrypt hashed. However there maybe people out there who wish to manually salt the hash to make it even more secure. A salt can be a username, for example, however it's better for it to be random.

Bcrypt uses a variant of Blowfish’s keying schedule and introduces a work factor. The work factor determines how expensive (i.e. how slow) the hash function will be. This helps to reduce brute force attacks.

Footnotes:

1: What is hashing and How Does It Work.
2: What is Salting in Password Security

Code highlighting provided by torchlight.dev.