Hashing Passwords with the PHP 5.5 Password Hashing API

    Sandeep Panda
    Sandeep Panda
    Share

    Using bcrypt is the currently accepted best practice for hashing passwords, but a large number of developers still use older and weaker algorithms like MD5 and SHA1. Some developers don’t even use a salt while hashing. The new hashing API in PHP 5.5 aims to draw attention towards bcrypt while hiding its complexity. In this article I’ll cover the basics of using PHP’s new hashing API. The new password hashing API exposes four simple functions:

    • password_hash() – used to hash the password.
    • password_verify() – used to verify a password against its hash.
    • password_needs_rehash() – used when a password needs to be rehashed.
    • password_get_info() – returns the name of the hashing algorithm and various options used while hashing.

    password_hash()

    Although the crypt() function is secure, it’s considered by many to be too complicated and prone to programmer error. Some developers then use a weak salt and weak algorithm for generating a hash instead, for example:
    <?php
    $hash = md5($password . $salt); // works, but dangerous
    But the password_hash()
    function can simplify our lives and our code can be secure. When you need to hash a password, just feed it to the function and it will return the hash which you can store in your database.
    <?php
    $hash = password_hash($password, PASSWORD_DEFAULT);
    That’s it! The first parameter is the password string that needs to be hashed and the second parameter specifies the algorithm that should be used for generating the hash. The default algorithm is currently bcrypt, but a stronger algorithm may be added as the default later at some point in the future and may generate a larger string. If you are using PASSWORD_DEFAULT in your projects, be sure to store the hash in a column that’s capacity is beyond 60 characters. Setting the column size to 255 might be a good choice. You could also use PASSWORD_BCRYPT as the second parameter. In this case the result will always be 60 characters long. The important thing here is that you don’t have to provide a salt value or a cost parameter. The new API will take care of all of that for you. And the salt is part of the hash, so you don’t have to store it separately. If you want to provide your own salt (or cost), you can do so by passing a third argument to the function, an array of options.
    <?php
    $options = [
        'salt' => custom_function_for_salt(), //write your own code to generate a suitable salt
        'cost' => 12 // the default cost is 10
    ];
    $hash = password_hash($password, PASSWORD_DEFAULT, $options);
    In this way, you are always up-to-date with new security measures. If PHP later decides to implement a more powerful hashing algorithm your code can take advantage of it.

    password_verify()

    Now that you have seen how to generate hashes with the new API, let’s see how to verify a password. Remember that you store the hashes in a database, but it’s the plain password that you get when a user logs in. The password_verify() function takes a plain password and the hashed string as its two arguments. It returns true if the hash matches the specified password.
    <?php
    if (password_verify($password, $hash)) {
        // Success!
    }
    else {
        // Invalid credentials
    }
    Just remember that the salt is a part of the hashed password which is why we are not specifying it separately here.

    password_needs_rehash()

    What if you need to modify the salt and cost parameters for the hash strings? This is a concern as you might decide to improve security by adding a stronger salt or larger cost parameter. Moreover, PHP might change the default implementation of the hashing algorithm. In all of these cases, you would want to rehash the existing passwords.

    password_needs_rehash()

    helps checks if the specified hash implements a particular algorithm and uses specific options like cost and salt while being created.
    <?php
    if (password_needs_rehash($hash, PASSWORD_DEFAULT, ['cost' => 12])) {
        // the password needs to be rehashed as it was not generated with
        // the current default algorithm or not created with the cost
        // parameter 12
        $hash = password_hash($password, PASSWORD_DEFAULT, ['cost' => 12]);
    
        // don't forget to store the new hash!
    }
    Keep in mind that you’ll need to do this when the user tries to login to your website as this is only time you have access to the plain password.

    password_get_info()

    password_get_info() accepts a hash and returns an associative array of three elements:
    • algo – a constant that identifies a particular algorithm
    • algoName – the name of the algorithm used
    • options – various options used while generating the hash

    Conclusion

    The new password hashing API is definitely easier to work with than fumbling with the crypt()
    function. If your website is currently running on PHP 5.5, then I strongly recommended that you use the new hashing API. Those who are using PHP 5.3.7 (or later) can use a library called password_compat which emulates the API and automatically disables itself once the PHP version is upgraded to 5.5.

    Frequently Asked Questions (FAQs) about PHP 5.5 Password Hashing API

    What is the PHP 5.5 Password Hashing API and why is it important?

    The PHP 5.5 Password Hashing API is a feature in PHP 5.5 and later versions that provides developers with a simple way to hash and verify passwords in a secure manner. It’s important because it helps protect sensitive user data. If a database is compromised, hashed passwords are much harder to crack than plain text passwords. The API uses a strong hash function, Bcrypt, by default, and automatically handles the generation of salt values, making it easier for developers to implement secure password handling.

    How does the password_hash function work?

    The password_hash function is a part of the PHP 5.5 Password Hashing API. It takes a plain text password and a hashing algorithm as input and returns a hashed password. The function also automatically generates and applies a random salt value to the password before hashing it. This salt value is included in the returned hash, so there’s no need to store it separately.

    What is the purpose of the password_verify function?

    The password_verify function is used to verify a password against a hashed password. It takes a plain text password and a hashed password as input. The function extracts the salt value and the hashing algorithm from the hashed password, applies them to the plain text password, and then compares the result to the original hashed password. If they match, the function returns true, indicating that the password is correct.

    How secure is the PHP 5.5 Password Hashing API?

    The PHP 5.5 Password Hashing API is considered very secure. It uses the Bcrypt hashing algorithm by default, which is a strong hash function. The API also automatically generates and applies a random salt value to each password before hashing it, which helps protect against rainbow table attacks. However, like all security measures, it’s not foolproof and should be used as part of a comprehensive security strategy.

    Can I use a custom salt with the password_hash function?

    Yes, you can use a custom salt with the password_hash function, but it’s not recommended. The function automatically generates a random salt value for each password, which is generally more secure than a custom salt. If you do choose to use a custom salt, it should be a random string of at least 22 characters.

    What is the cost parameter in the password_hash function?

    The cost parameter in the password_hash function determines the computational cost of the hash. A higher cost makes the hash more secure, but also slower to compute. The default cost is 10, which is a good balance between security and performance for most applications.

    How can I check if a hashed password needs to be rehashed?

    You can use the password_needs_rehash function to check if a hashed password needs to be rehashed. This function takes a hashed password, a hashing algorithm, and optionally a cost as input. It returns true if the hashed password was created with a different algorithm or cost, indicating that it should be rehashed.

    Can I use the PHP 5.5 Password Hashing API with older versions of PHP?

    The PHP 5.5 Password Hashing API is only available in PHP 5.5 and later versions. However, there is a compatibility library available that provides the same functionality for PHP 5.3.7 and later versions.

    What happens if I hash a password with the PASSWORD_DEFAULT constant and then the default algorithm changes in a future version of PHP?

    If you hash a password with the PASSWORD_DEFAULT constant and then the default algorithm changes in a future version of PHP, the password_hash function will continue to work as expected. The hashed password includes information about the algorithm used, so the password_verify function can still verify the password correctly.

    Can I use the PHP 5.5 Password Hashing API with non-ASCII passwords?

    Yes, you can use the PHP 5.5 Password Hashing API with non-ASCII passwords. The password_hash and password_verify functions work with binary data, so they can handle passwords with any characters. However, you should be aware that different systems may handle non-ASCII characters differently, so it’s a good idea to normalize passwords before hashing them.