Bcrypt Passwords with PHP 5.5

By Phillip Harrington on 11/7/2014


How Not To Store Passwords

Marty Weiner wrote a great a great article on how not to store passwords. He discusses the problems with passwords, how not to do it, and gives his recommendation of the right way to store passwords. Go read his article now.

How To Store Passwords

Marty recommends using bcrypt and gives examples in a lot of languages except PHP. Here's how to do it in PHP 5.5 and up (but maybe not 6?).

Bycrypt With PHP

PHP 5.5 Makes It Easy

Use the password_hash function, and pass in the constant for the bcrypt algorithm, which is PASSWORD_BCRYPT. Also provide an appropriate $cost.

Here's its signature:

password_hash($password, $algorithm, $options = []);

And here's an example of how to use it:

$password = 'H@X04!';
$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => $cost]);

The return value will be the hash. Store this somewhere. A database, perhaps.

Note that you can also pass a 'salt' in the $options array. DON'T DO THIS. Let the salt be generated for you randomly.

What's my $cost?

The appropriate $cost to use depends on your hardware, and how quickly you would like the $hash to be computed. The PHP manual provides a simple function you can run once on your server to find a good $cost. It will probably be 10 or 11.

// 100 milliseconds
// change this to your target time
$timeTarget = 0.1;

$cost = 8;

do {
    $cost++;
    $start = microtime(true);
    password_hash('test', PASSWORD_BCRYPT, ['cost' => $cost]);
    $end = microtime(true);
} while (($end - $start) < $timeTarget);

echo 'Appropriate Cost Found: ' . $cost . PHP_EOL;

Validate The Password

Validating the password is equally easy:

// true, hooray!
password_verify($password, $hash);

// false
password_verify('not the password', $hash);

// false
password_verify($password, 'not the hash');

Here the $password will be what the user provides.

But I don't have PHP 5.5!

Upgrade already!

Before PHP 5.5

Use ircmaxell's password_compatibility library. This requires that crypt is enabled.

Go Forth!

Take the time to upgrade your authentication layer now or you open yourself up to liabilities galore. Helpful hackers should probably be forking ZFCommons ZFUser and other libraries as we speak.