Password Hashing in PHP, The Right Way™

I took time recently to read up on best methods for generating and storing user password hashes. The ‘base’ I often use for websites, in PHP, hasn’t been updated in a while and needed some updating on the login side of things. This article at crackstation.net was pretty much everything I used while updating how my base hashes user passwords and generates and stores the salts.

Previously, I was using the same, static salt for everyone, but found that to be a less than optimal practice, from a security standpoint. Everything I did was pretty heavily based on the PHP source provided in the crackstation.net piece.

Using a random salt means that you need to keep track of it somehow, and that’s usually done by saving the salt in the database, along with the password hash and other user info. But, if your database is compromised, the salt used in creating the password hash is readily available for the attacker. And that’s not a good thing.

So, in addition to the stuff described in the Crackstation.net article, I also use a static, but still random string that gets appended to each random salt. Now, if my database is compromised, but my filesystem is still secured, attackers won’t have the entire salt. The static string that we add to the random salt should only be accessible from our PHP source, which is on the still secure filesystem.

If you can, use a third-party library for password hashing, like phpass, which is used in projects like WordPress and Vanilla. It’s very popular, and for good reason.

Another good library for passwords in PHP would probably be PHP Password Library. I’ve never used it myself, but it looks like it’d be really easy to integrate into existing code, and can be installed via Composer.

Also, if you’re able to run PHP 5.5.x, you can make use of the new password hashing functions, password_hash() and password_verify(). This article at Sitepoint gives a good overview of the new functions.

If you’re on an older version of PHP (anything below PHP 5.5.0) and would like to use the new password hashing functions, you should look at ircmaxwell/password_comapt on github. It provides forward-compatibility with the password_* functions found in PHP 5.5.

So, there’s no shortage of good options for helping out with password hashing. And if you do need to roll your own, you can use a function like openssl_random_pseudo_bytes() or mcrypt_create_iv to generate the salt.

I’m generating random salts using openssl_random_pseudo_bytes() and using MySQL’s sha2 function for password hashing. sha2() was added in MySQL 5.5.5, so it probably won’t be available to you if you’re using an earlier version. Although I believe many linux distributions have a patched version.

Did I mess something up? Please let me know if I’ve missed something or if I’m just totally off base somewhere. Comments are open.

Edit: As Matt noted in the comments, sha2 isn’t a very good choice, so I’m going to use now using the password_comapt library, hello bcrypt.