In the early days of PHP, if you wanted to store passwords you had to do a lot of the work yourself – this left many systems vunerable, as it was only half implemented or done badly. Since then, however, the team behind developing PHP has been hard at work making the whole process much easier (thus increasing overall security).
With the release of PHP 5.5, two new functions are available for password management which we’ll cover in this tutorial. These functions are
<a href="http://php.net/manual/en/function.password-hash.php" target="_blank">password_hash</a> and
<a href="http://php.net/manual/en/function.password-verify.php" target="_blank">password_verify</a>.
This function allows you to simply create a salted and secure password, ready to use. At the moment Blowfish encryption is the only option when using this function, but as an encryption method, it’s up there with the best and more algorithms are likely to follow.
It uses PHP’s
crypt method, which means if you’re already using crypt with Blowfish, you can swap over with no disruption to current passwords. To use
password_hash, you just need to specify the string to hash and the algorithm to use.
$original = 'password'; echo password_hash($original, PASSWORD_BCRYPT); // Output: $2y$10$ZGvP.EbzBX7v/3JaQkC/NOTXej4BGigIrJJH1bapuIIL.WhjTD3cm
The outputted string will always begin with a dollar ($) symbol, followed by
2y (meaning Blowfish), another $, the number of times the password is re-hashed (aka the cost) and finally the hashed password.
You can increase the cost with a third parameter:
['cost' => 12].
It’s great if we can securely store the password, but it doesn’t mean much unless we can check to verify a user is who they say they are. The
password_verify function exists for this, by comparing a given string to a stored password. The passwords generated from password_hash are done with one-way hashing, so they can’t be decrypted – but the reverse is possible. The inputted attempt can also be hashed in the same way and then compared with the stored string.
$toCheck = 'password'; $valid = password_verify($toCheck, '$2y$10$ZGvP.EbzBX7v/3JaQkC/NOTXej4BGigIrJJH1bapuIIL.WhjTD3cm'); // $valid == true
Using this, you can then see if the user should be logged in or kicked out, as it will return true if they match. The best way to do this is to wrap it in an if statement.
This is only one part of a complex login system needed. For example, a way of blocking or delaying users if they have too many incorrect attempts is needed so your system is much harder to brute-force. Another example of a needed feature is a way to keep a user logged in once they have the correct password and give a reasonable timeout to this.
All these details on how you can build a full login system can be found out with a quick internet search.
hash_equals also exists as a way of checking, but is generally used to compare two hashed passwords.
hash_equals functions are timing safe (more info on timing attacks). This is another advantage to using them over older methods as they take a consistant amount of time to return, as pointed out by Jordan.