What is the "best" solution these today?
This seems a good option: https://defuse.ca/php-pbkdf2.htm
But then how about upgrading to PHP5.5 and using this? http://php.net/manual/en/function.hash-pbkdf2.php
Curious as to why the PHP site states:
Caution The PBKDF2 method can be used for hashing passwords for storage (it is NIST approved for that use). However, it should be noted that CRYPT_BLOWFISH is better suited for password storage and should be used instead via crypt().
For PHP versions less that 5.5 would it be fair to use the defuse.ca solution, and then just switch it out after upgrading to PHP5.5?
/*
* PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt
* $algorithm - The hash algorithm to use. Recommended: SHA256
* $password - The password.
* $salt - A salt that is unique to the password.
* $count - Iteration count. Higher is better, but slower. Recommended: At least 1000.
* $key_length - The length of the derived key in bytes.
* $raw_output - If true, the key is returned in raw binary format. Hex encoded otherwise.
* Returns: A $key_length-byte key derived from the password and salt.
*
* Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt
*
* This implementation of PBKDF2 was originally created by https://defuse.ca
* With improvements by http://www.variations-of-shadow.com
*/
function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
{
$algorithm = strtolower($algorithm);
if(!in_array($algorithm, hash_algos(), true))
die('PBKDF2 ERROR: Invalid hash algorithm.');
if($count <= 0 || $key_length <= 0)
die('PBKDF2 ERROR: Invalid parameters.');
$hash_length = strlen(hash($algorithm, "", true));
$block_count = ceil($key_length / $hash_length);
$output = "";
for($i = 1; $i <= $block_count; $i++) {
// $i encoded as 4 bytes, big endian.
$last = $salt . pack("N", $i);
// first iteration
$last = $xorsum = hash_hmac($algorithm, $last, $password, true);
// perform the other $count - 1 iterations
for ($j = 1; $j < $count; $j++) {
$xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true));
}
$output .= $xorsum;
}
if($raw_output)
return substr($output, 0, $key_length);
else
return bin2hex(substr($output, 0, $key_length));
}
This is the current solution from defuse.ca, would it be fair to rename this function to hash_pbkdf2() and after upgrading to PHP5.5 transition would be nice and smooth?
The accepted best practice in PHP passwords, as of PHP 5.5, is
password_hash
. It presents a single, unified, built-in, future-compatible way to generate a secure password hash.If you are using a security-updated version of 5.3.x or higher, you can use the password_compat library instead.
Under the covers, the current version makes calls to
crypt
with some predefined security options. Future versions may change the default options.Please be sure to carefully read the section on the
crypt
page that talks aboutCRYPT_BLOWFISH
versioning, as well as review the versioning notes on the password_compat page.As noted clearly in the warning message, PBKDF2 is accepted by the NIST as an adequate way to store passwords. You can use implementations of it without significant concern, but you should only do so if you either need support for PHP versions prior to 5.3, or need to support PHP versions that have a broken
CRYPT_BLOWFISH
.