Back-ported hash_pbkdf2() from PHP 5.5
Tuesday, January 22. 2013
PHP has been lacking properly implemented password-hash function. Many web-sites really would benefit from having such a thing available. Zend Framework -guys implemented that into their ZF2. Nice! But for us not running ZF2, doing 1000 hashes in a loop with PHP-code does not sound like a good idea.
Initially I thought that Mcrypt-project would implement PBKDF2 and PHP would gain the function that way. Apparently they're not interested either.
The good news comes from PHP-project. They implemented hash_pbkdf() into native PHP. Great! The problem is, that PHP 5.5.0 has not been released yet. I didn't want to wait and back-ported the function from PHP 5.5.0 source tree into my own 5.4.11.
For those wanting to build their own, the patch is here: php-5.4.11-pbkdf2.patch
The test from PHP manual page:
$hash = hash_pbkdf2("sha256", $password, $salt, 1, 20);
echo $hash . "\n";
Yields exactly correct result: 120fb6cffcf8b32c43e7
Doing only 1 round is very naive. The recommended minimum is 1000 and apparently 2000 is the way to go. I took Zend Framework's Zend\Crypt\Key\Derivation\Pbkdf2 as a reference and did 2000 rounds instead of 20. Both algoritms return exactly the same result, though they handle the length-parameter differently. ZF2 assumes bytes, but PHP's native version assumes hex-string length. But I did iron out the difference in my code.
The native version does 2000 rounds in 0.00674 seconds, and native PHP-version does that in 0.012470 seconds, so C-compiled binary is 100% faster.
My test code for native version:
<?php
$password = "password";
$salt = "salt";
$now = microtime(true);
$hash = hash_pbkdf2("sha256", $password, $salt, 2000, 20);
$dura = microtime(true) - $now;
echo $hash . "\n";
echo sprintf("%12.11F", $dura) . " seconds\n";
?>
My test code for Zend Framework 2 version:
<?php
require_once 'Hmac.php';
require_once 'Pbkdf2.php';
$password = "password";
$salt = "salt";
$now = microtime(true);
$hash = Zend\Crypt\Key\Derivation\Pbkdf2::calc("sha256", $password, $salt, 2000, 10);
$dura = microtime(true) - $now;
echo bin2hex($hash) . "\n";
echo sprintf("%12.11F", $dura) . " seconds\n";
?>
If you're site is not storing passwords properly, its about time to start now.
Diary of a Pentester
Wednesday, January 16. 2013
There is this guy, whose hobby is to do penetration testing for websites of his interest. He's a white hat -guy, so he does his best to inform webmasters. Quite often he reaches nobody and eventually publishes his findings.
Janne's blog is at http://janne.is/. I'd sure hate to see one of my sites listed there.