Creating and Verifying Hashes in PHP 5.5
jcurcio.com
jcurcio.com
But that didn't always happen. There do exist experienced PHP devs who would do password storage the right way but PHP up until now neither made it easy nor encourage these practices as they relate to passwords. Now I hope word gets out about this and people stop using md5() thinking their passwords are safe. Not that md5 is necessarily bad, but most people don't realize there are better tools for maintaining secure passwords.
Also, this reminds me a little bit of `has_secure_password` method in Rails minus some of the automation that comes with it.
I'm happy to be one of them! The app I'm currently building uses this bcrypt library, and I can only highly recommend it:
Looking back now it seems obvious but back then it just too overwhelming. With PHP there's this 'just get it done' attitude and futzing around with phpass wasn't something I could let myself do back then.
Of course I now regret it. I ended up using a different encryption library for password storage on my app. It isn't md5 but I know it could and should be stronger. So now I'm in a situation where I'm rewriting the codebase in a different language entirely and the cherry on top is that I need to migrate all my user's passwords and even some data from the original method to bcrypt, which I'm now using. It seems simple in theory but I have a feeling this is going to cause some headaches. However, its totally necessary and especially for the type of application I'm working on which puts a big focus on privacy and security.
If the new column isn't blank, then the have already logged in and you have the new hash, so verify against the new hash. As everyone logs into your website, you'll have a new set of, more secure, hashes. For those that are inactive you can either delete them, assign a random password and email them, or let their MD5 password hash sit there forever.
Over time, active users get their password upgraded.
Then after a longer time, just reset the passwords of the users who never logged in since you started migrating.
On signup store:
$password = password_hash(md5($password),PASSWORD_BCRYPT);
And on login: password_verify(md5($password), $password_hash);
Then you just have apply password_hash() on all you passwords in database.Bonus the migration is instantaneous, you don't need a 6 month transition period.
IMHO it do not reduce the security, but i'm not a crypto expert though.
So adding an extra md5 hashing is totally insignificant (in term of computation).
As much as I welcome these features, I don't think that's true. PHP has made it extremely easy to use the core operating system's hashing features.
http://us3.php.net/manual/en/function.crypt.php
And after 5.3, even if for whatever reason your operating system is lacking, they were built in for convenience.
This is really, really dumb and pointless. In fact it makes absolutely no sense, it tells password_hash to use a bcrypted "MySalt" as a salt.
Not only is there no reason to explicitly provide a salt unless you already have bcrypted passwords in a non-standard format, (in which case you'd pass the existing $salt directly, you wouldn't bcrypt it) this is an inane way to generate one.
If you want to generate your salt by hand, don't do it. If you really, really, really want to, use mcrypt_create_iv.
Edit: also the default cost is already 10, you should offer the $options as an aside and not suggest using them as standard practice.
I don't think it's dumb and pointless at all, really. Generally you wouldn't generate a salt yourself if you're using bcrypt however I'm sure there would be cases where it would be needed or even preferred for some reason. I would advocate for flexibility and education rather than rigidity and simplicity. That is to say, rather than make the function useless to those who'd need their own salt I think it's a better idea to allow these options while making sure developers know that they should only be used in certain situations. A function like this isn't bad because it can be misused.
I have nothing against adding a salt manually to show how it works, I have things against adding stupid salts.
> I don't think it's dumb and pointless at all, really.
You're missing the criticism. The problem isn't the ability to inject a salt (it is useful e.g. when the (cost, salt, hash) triple is in a format other than MCF), it is the way the salt is obtained.
A use case for manually injecting the salt is when your KDF result isn't stored in Modular Crypt Format, and thus you can't just pass it to `password_verify`.
In that case, you get your stored cost and salt, explicitly inject them into `password_hash` and use a constant-time string comparison (which I'm not sure PHP provides, so there's a potential security hole here) instead of `password_verify`.
https://github.com/ircmaxell/password_compat
Written by Anthony Ferrara, the same guy behind the `password_*` API in PHP 5.5
This is true for WordPress, which uses PHPass. You have to replace `wp_hash_password` to get WP to use bcrypt: http://wptip.me/wordpress-bcrypt
I've worked on password hashing recently, and I think the best interfaces should take only a password, and return a hash. Modern password hashing algorithms, e.g., bcrypt, scrypt, etc., usually also need a set of local parameters. The API should hide them as well, and expose only a set of interfaces with safe and sound preconfigured parameters, which in turn determine how much CPU time and memory space will be used. One disadvantage of this approach is that it exposes the local parameters, hence make it a little bit easier for attackers.
This is exactly how crypto primitives have been designed. If the designers of AES ever let people choose the key size, sooner or later some people would shoot themselves in the foot, and set the key size to 1-bit. If you think this is an extreme example, it actually has happened, not in some obscure API that nobody uses, but in the very XMLDsig standard published by W3C [1].
Regarding password hashing standards, I found many misuses of libscrypt that would make it extremely easy to recover passwords. But I'll save the details for another blog post or something.
[1] http://www.w3.org/QA/2009/07/hmac_truncation_in_xml_signatu....
As another option, you can also just not build any password infrastructure. We do all the hashing and authorization as a secure service and there are PHP devs of all levels using it... http://www.stormpath.com/docs/php/quickstart
http://pythonhosted.org/passlib/lib/passlib.hash.bcrypt.html...
Basically you want to use as high of a cost as you can on your servers hardware, without producing a noticeable slowdown to the end user.
A simple benchmark with results: http://pastebin.com/NiqKEAVm
Canonical article on why bcrypt which explains it here