Recently PHP 5.5 was released into beta, which puts us one step closer to another release of PHP. This week, I thought I would spend a little time explaining a new feature that will be implemented in 5.5 that will hopefully make dealing with passwords easier for developers to grasp and properly implement. I cannot tell you the number of apps, even ones written within the last year or so, that I open up only to find either an md5 hash, or worse, clear text password storage. I keep telling myself that eventually this will come to an end, and people will stop taking the easy way out. Maybe PHP 5.5 will have made it so easy that there is simply no further excuse not to implement solid password hashing.
PHP 5.5 will implement a new API for password hashing which acts as a wrapper around the crypt() function, with the goal of simplifying its use to for a successful implementation. As this API will be an integral part of the PHP core, there are no external requirements or additional installation needed. Additionally, there is no configuration available for this API via directives in php.ini.
There are 4 functions in the API, the first being password_get_info() . This function accepts a single parameter, $hash , which must be a valid hash created using a hashing algorithm that is supported by the password_hash() function. The function returns an array which is structured as follows:
$arrHashInfo = array(
'algo' => 1,
'algoName' => "bcrypt",
'cost' => 10
// algo : an integer representing the password algorithm constant
// algoName : human friendly name of the hashing algorithm
// options: the options that were used when calling password_hash()
The next function is called password_hash() and is used to create hashes. It requires 2 parameters, with a 3rd optional:
- $password: a clear text string to be hashed
- $algo: an integer of the algorithm constant being used (e.g. 1 = bcrypt/blowfish)
- $options [optional]: options to use, currently only ‘salt’ and ‘cost’ are available for use. If omitted, a random salt and default cost are used.
This function returns the hash if successful. In the case of failure, the function will return FALSE .
The third function, password_needs_rehash() is used to determine whether or not a given hash meets the requirements as specified in the options given. Three parameters are accepted for this function:
- $hash: a string of the password hash
- $algo: the algorithm that the hash is being checked against
- $options [optional]: an array of options used to verify the hash against. As with password_hash() , there are 2 choices, salt & cost. If this parameter is omitted, the default cost is used.
This function returns TRUE if the password needs to be rehashed, and FALSE if it doesn’t.
Finally, the password_verify() function is used to verify a clear text string against a specified hash. This function accepts only 2 parameters and both are required. The first is $password , which is the clear text string of the user’s password, and the second is the $hash itself; the one you store in the database for instance. This function returns TRUE if the password matches the hash, and FALSE if it does not.
Benefits of this API
As I was reading up on this subject, I found a considerable amount of dialog about it, and whether or not it was useful or better than what is already available. There is also a lot of spirited discussion about the fact that this in not an object oriented implementation, and that the implementation does not use namespaces. If you are interested in that part of the debate, and the thought process behind it, you can read all about it on Reddit.
All things being equal, the main benefit of this is clear, at least to me. The process of hashing a password using PHP is being made much much easier. What’s more, the algorithm used in this implementation is far superior to what most new developers would choose on their own. What’s more, this is built for the future and will allow easier integration of newer, stronger algorithms as they are developed and then vetted to assure that they are robust.
I like this API because it is abundantly clear what it is for. Someone searching the PHP manual or whatever for the term
password will come across this and know that this is what should be used. As it stands today, a new developer walking into PHP may have to choose between md5, sha, crypt, and then read and research further to figure out which one to use and with which options, etc. That leaves a lot of room for error, especially when the easiest methods like md5 are the least secure. In a world where human beings are known for choosing the easiest option, or taking the path of least resistance, it is nice to see that, starting with PHP 5.5, the path of least resistance is going to be durable and robust. I am looking forward to using it in my apps.
To wrap this one up, I think that Anthony Ferrara (@ircmaxell) has done a great job seeing this one through to acceptance, and for that, I am very grateful. This is a step in the right direction for PHP, and though it may seem like a nice new wrapper for technology that already exists to those with a lot of experience in this area, newer developers should find it to be a refreshingly simple way to put strong password encryption into their applications. Making security easier to implement correctly benefits not only the developer, but also the PHP community at large.
Best of luck in all your PHP endeavors!