How to use the PHP 5.5 password hashing functions
PHP 5.5 introduced some very interesting password hashing functions that will make your life much much easier, the web much much safer and obviously that’s the beginning of better times when it comes to application security. Those functions make it extremely easy to create and verify password hashes. To understand how they work, have a look on this code and try to run it on your PHP 5.5 environment.
Please note: To make these functions available in PHP 5.3.7+ (minimum requirement!) or PHP 5.4+, include the password compatibility library by Anthony Ferrara (who’s the developer of those functions by the way).
<?php // THESE FUNCTIONS WILL WORK WITH PHP 5.5 // if you want to use them with PHP 5.3 or 5.4 you'll need to include // the lib/password.php file from this project: // https://github.com/ircmaxell/password_compat/ echo "Please note: These functions need at least PHP 5.3.7<br/>"; echo "You are running PHP ".phpversion(); echo "<br/>"; // hashing & salting a password (salt will be auto-generated) $pass = 'mysecretpassword'; $hash = password_hash($pass, PASSWORD_DEFAULT); echo $hash; echo "<br/>"; echo "Length hash: ".strlen($hash)."<br/>"; // checking if the password fits to the saved hash/salt-string var_dump(password_verify($pass, $hash)); echo "<br/>"; // checking if the password fits to the saved hash/salt-string // intentionally using a wrong password $wrong_pass = 'atotallywrongpassword'; var_dump(password_verify($wrong_pass, $hash)); echo "<br/>"; // getting info from hash string, useful for checking if the hash // is outdated (happens when your hashes are hashed with cost // factor 7, but after some time you decide to increase it to 8) var_dump(password_get_info($hash)); echo "<br/>"; // checking the password rehash function // same cost factor like before, so the function should return false $options['cost'] = 10; var_dump(password_needs_rehash($hash, PASSWORD_DEFAULT, $options)); echo "<br/>"; // we increase the cost factor, so the function should return true $options['cost'] = 11; var_dump(password_needs_rehash($hash, PASSWORD_DEFAULT, $options)); echo "<br/>"; // let's rehash a password with the new cost factor from $options: // (btw 10 is the internal standard) $hash = password_hash($pass, PASSWORD_DEFAULT, $options); echo $hash; echo "<br/>"; echo "Length hash: ".strlen($hash)."<br/>"; // finally, some time tests: cost factor 7 $options['cost'] = 7; $runtime_start = microtime(true); password_hash($pass, PASSWORD_DEFAULT, $options); $runtime_end = microtime(true); $runtime_total = $runtime_end - $runtime_start; echo "Runtime with cost factor 7: ".$runtime_total." seconds<br/>"; // finally, some time tests: cost factor 10 $options['cost'] = 10; $runtime_start = microtime(true); password_hash($pass, PASSWORD_DEFAULT, $options); $runtime_end = microtime(true); $runtime_total = $runtime_end - $runtime_start; echo "Runtime with cost factor 10: ".$runtime_total." seconds<br/>";
This will generate output like this:
Please note: These functions need at least PHP 5.3.7 You are running PHP 5.3.21 $2y$10$/m.xxwGqroKHnI6/5XrsQOKMmejfFMmOW8JuLnAT.TLbTboyfi1.6 Length hash: 60 bool(true) bool(false) array(3) { ["algo"]=> int(1) ["algoName"]=> string(6) "bcrypt" ["options"]=> array(1) { ["cost"]=> int(10) } } bool(false) bool(true) $2y$11$/YaA58m4HcKxmzva0AJnceWyeD9pKBSq.dJfpUGbwZgpAxPCoxHRe Length hash: 60 Runtime with cost factor 7: 0.019093036651611 seconds Runtime with cost factor 10: 0.14752817153931 seconds
PHP 5.5 password hashing summarized:
Generate a hash from a real password: [Offical manual page here]
$pass is your password, PASSWORD_DEFAULT is a PHP internal constant that defines the used hashing algorithm (PHP itself might change this when time goes by to keep in that with current server hardware improvements):
password_hash($pass, PASSWORD_DEFAULT);
Check password: [Official manual page here]
To check if password $pass (from user login form usually) fits the database-saved hash $hash:
password_verify($pass, $hash);
Additionally, for people who know what they to:
Check if your password needs to be rehashed: [Official manual page here]
(because you changed your server hashing cost factor settings): where $hash is the database-saved hash, PASSWORD_DEFAULT (see above) is the PHP internal hash algorithm constant and $options is an array of options, usually only the “cost” key is interesting. Imagine that you were using a cost factor of 8 for years, and now you changed the cost factor to 10 (somewhere in your app’s configs, here in this example represented by this line: $options[‘cost’] = 10;), then this function will check if your database-saved hash needs to be rehashed (via password_hash();) and saved again to the database.
$options['cost'] = 10; password_needs_rehash($hash, PASSWORD_DEFAULT, $options);
Read out the hashing infos from a hash: [Official manual page here]
Every hash created by password_hash() provided extractable information about the used hashing algorithm (in a coded and a human-readable version) and about the used cost factor. Get the info array via:
password_get_info($hash);
By the way, all those ultra-modern functions are used in all versions of the php-login script, if you don’t know it yet, have a look here: http://www.php-login.net