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.
timoh on :
Any reason to prefer PBKDF2 over bcrypt?
Jari Turkia on :
Recommended reading: "Don't use bcrypt"
http://www.unlimitednovelty.com/2012/03/dont-use-bcrypt.html
The name of the article sounds worse than it actually is.
My own thinking is that we need both in PHP and I'd like to use PBKDF2.
timoh on :
It boils down to cracking/validation ratio, and according to the experts, PBKDF2 gives more advantage to the attacker.
About the blog post, it seems the author has some false assumptions about the subject.
I don't mean PBKDF2 is a bad choice, but among the experts, it is not considered to be "as good as" bcrypt. And it has some real (political) use cases because it is NIST approved
I'll add a few links regarding password hashing topic:
http://www.openwall.com/presentations/Passwords12-The-Future-Of-Hashing/
http://daemonology.net/papers/scrypt-2012-slides.pdf
http://security.stackexchange.com/questions/4781/do-any-security-experts-recommend-bcrypt-for-password-storage/6415#6415
Jari Turkia on :
Open-source (and PHP) is about freedom. When it comes to PHP as programming language, we need to have the necessary tools and functions for everybody. That includes all reasonable hashing mechanisms for managing passwords.
You seem to have a very strong opinion about bcrypt as the choice for storing passwords. You don't reveal the actual reasoning behind that, but the in the links you provided, the much of information is about difficulty of brute-force hacking passwords.
My primary line-of-defence is not to allow unauthorised access to my userbase, that is completely outside the scope of chosen hash-mechanism. My secondary line-of-defence is to store user passwords in a way, that in case the user database leaks, the information is not easily usable.
The tool I chose for hashing is PKBDF2 due to extensive scientific research done with it. I don't much care about politics or some foreign organization's recommendations. Politics is for useless people, who cannot actually do anything. Organizations always have an angle they want to achieve. So, in the end I'll have to make up my own mind.
If the only criteria for hashing mechanism would be the amount of resources need to brute-force hack a single password, I don't understand why everybody wouldn't use scrypt. It can maximally exhaust attacker's resources to the point that for example a FPGA-based hardware would not be feasible. In my mind, in real world there are other aspects to consider.
Meanwhile, I'm exploring possibilities of implementing existing scrypt library into PHP as an extension.
timoh on :
The first link I posted (openwall.com), "Password security: past, present, future", should give quite a good view on the topic. And from there you can see some of my reasoning about bcrypt being stronger than PBKDF2.
You can actually probably test it by yourself too (at some level). Create two password hashes on your web server, using bcrypt and using PBKDF2 (just make sure you create the PBKDF2 hash using your patch, so the PBKDF2 function is not written in userland PHP code). Tune them both to take about the same time (say, 50ms or so). Then attack those hashes using CPU/GPU, using John the Ripper and Hashcat/oclHashcat, for example. Now you should see the concrete difference between bcrypt and PBKDF2. Of course this is not a "real test", but anyway, it should give some view.
My original point was to correct your writing "PHP has been lacking properly implemented password-hash function". We have CRYPT_BLOWFISH and CRYPT_SHA512 for example, via crypt(), in PHP. Both of those are proper password hash functions (as is PBKDF2, too).
About scrypt, I think the primary reason is scrypt's age (and it is not included in PHP). And also, I'm not sure how well it works in a typical web app system (interactive logins). Most probably better than bcrypt, as long as it can be used with reasonable settings. But anyway, scrypt is from 2009 and bcrypt, for example, is from 1999.
Btw, if you were not already, you might be interested to follow this mailing list: http://www.openwall.com/lists/crypt-dev/
Jari Turkia on :
Do you have any comments about following points I made in my earlier post:
- Open-source?
- Freedom of choice?
- Password hash not being the only defence?
- Difference in amount of scientific research made with bcrypt or PKBDF2?
About scrypt suitability as a Key Derivation Function, I have to completely disagree with you. Even Wikipedia article says "One concrete instance of such an algorithm is the scrypt function, based on the concept of ...". If you have any kind of hard evidence about scrypt's unsuitability, I'll be happy to investigate that. In the meanwhile I'll be working with the hash-extension for PHP.
timoh on :
I'm just bringing up some techical details, but of course everybody is free to use whatever they like
But yes, at this point of time, for PHP applications, I would recommend the use of bcrypt for password hashing, when dealing with interactive logins (typical web apps).
> Do you have any comments about following points I made in my earlier post...
I'm not sure how the three first points relate to this conversation about bcrypt and PBKDF2. I'll just stay in the subject.
About difference in amount of scientific research between bcrypt and PBKDF2, I think whatever the solid difference is, it is not significant, in a manner that it would not be safe to recommend using bcrypt or PBKDF2.
Both are well studied, well known and mature algorithms. And they both are quite a bit more mature than scrypt.
I don't recall saying anything about scrypt's unsuitability? Maybe you misread (I'm not sure what parts you do disagree with)? I just brought up scrypt's age, and that it needs to be used with proper settings (using it like Litecoin did, actually made it weaker than bcrypt would have been). And also, I don't have enough knowledge about scrypt to make solid straightforward sayings (to recommend/not recommend) about it's suitability for use in web apps. Thats why I wrote "I'm not sure..".
These kind of points are good to acknowledge.
Jari Turkia on :
Being on the subject: I'm still waiting for your comments about PHP and need for other hashing functions.
I'll put emphasis on the facts I already stated:
- store the passwords using something else than hash
- we need to have more options in PHP
- developers need to make the choice based on their needs
- password hashing function must NOT be the only method of protection for passwords, as the amount of brute-force computing resources must not be only criteria for implementing security in software
Feel free to comment on any of those. In my definition of the subject of this thread, they are included. Meanwhile I'll address your comments:
- point me to any research done on bcrypt, I didn't find any
- your statement "I think the primary reason is scrypt's age. And also, I'm not sure how well it works in a typical web app system" can be very easily understood as "not suitable for PHP"
- the number of references for scrypt KDF is huge, but it looks like nobody has a decent implementation of it, so why not make one
timoh on :
I'll mention this once more, I made my initial comment because of this "PHP has been lacking properly implemented password-hash function". I pointed out that it is not the case.
> - store the passwords using something else than hash
Makes sense, naturally.
> - we need to have more options in PHP
I understand PBKDF2 can be included because of political reasons. But in general, are you sure "more options" is the way to go in this case? How would one benefit from having more choices which are not as good as what we already have?
> - developers need to make the choice based on their needs
This looks questionable to me. Can they make educated choices? In my opinion, this is the way to go: https://github.com/ircmaxell/password_compat
> - password hashing function must NOT be the only method...
Right.
> - point me to any research done on bcrypt, I didn't find any
I think you were looking for wrong papers. Bcrypt is based on Blowfish and it is certainly well studied. See the first comment by moxie: http://news.ycombinator.com/item?id=3724560
> - your statement...
What I mean is that I don't have enough knowledge on this to make educated recommendations. But recall, I wrote: "Most probably better than bcrypt".
Jari Turkia on :
I fully respect some of your points-of-view when it comes to password hashing, but your lack of respect for my views and insulting behaviour make the respect part really hard. For reason yet unknown to me, you start a holy war so that everybody must use bcrypt just because you say so. Apparently somebody made you a King. I didn't get the memo about that. However, in open-source development me and other hard working developers get to do as they wish, regardless of your opinions. We get to have our way, even if mainstream PHP never agrees on our changes and extensions.
Btw. the current state of hashing in PHP is disgraceful. There are number of modules for that, and some functions are sprinkled in String-module. That I view as poorly implemented. The newest addition of password hashing -module for PHP 5.5 is definitely a step into right direction.
Your last move when you insult the intelligence of PHP developers is a low punch. Apparently from your throne everybody else looks as feeble subjects of your kingdom and must do as you say without asking questions.
I wish you all the best in your ventures! At this time our paths diverge.