OverDocs

Hashing passwords Edit on GitHub In category: PHP

Introduction #introduction

Hashing passwords in proper way is crucial for application security. You should always be prepared for possible database leak. Luckily, since PHP 5.3.7 we can utilize a very convenient set of functions: either built into PHP or using a compatibility library.

PHP core functions(Applicable in versions: PHP 5.5+) #core

Under at least PHP 5.5 you don't need to perform any additional steps as password_* functions are available by default.

Compatibility library(Applicable in versions: PHP 5.3.7+) #compat

Since password_* functions are just friendlier wrappers for existing ones, you can use pure PHP implementation for PHP versions greater than 5.3.7 and lower than 5.5.

The library was made by one of the developers of PHP. You can download it from GitHub or install using Composer.

Basic operations #operations

The following code listing shows basic operations on passwords and their hashes:

<?php
// Hashing string using default algorithm
echo password_hash('secret', PASSWORD_DEFAULT);

// Hashing password using bcrypt and setting additional options
$options = array(
    'cost' => 10,      // See the section below to learn more about setting cost
    'salt' => 'custom' // Use your own salt instead of automatically generated one
);

echo password_hash('secret', PASSWORD_BCRYPT, $options);

// Verifying if the password matches a hash
if (password_verify('secret', $hash)) {
    echo 'Password is valid';
} else {
    echo 'Password is invalid';
}

Warning

When comparing hash with a password, you should always use password_verify(), not a regular comparison operator. It prevents from timing attacks.

Note

The default algorithm at the moment is bcrypt but it may be changed in the future - that's what PASSWORD_DEFAULT was created for. In most cases it provides the strongest and safest algorithm currently available.

Finding optimal bcrypt cost #bcrypt-cost

When using bcrypt, you can set a hashing cost, like it was shown in code above. The bigger the cost, the longer the strongness of hash and resource usage.

Therefore you should calculate the optimal cost, which depends on capabilites of your server.

<?php
// Desired hashing time in seconds
$timeTarget = 0.05;

// Start from 8 - it is good baseline, but we might afford to use higher cost
$cost = 8;
do {
    $cost++;
    $start = microtime(true);
    password_hash('test', PASSWORD_BCRYPT, array('cost' => $cost));
    $end = microtime(true);
} while (($end - $start) < $timeTarget);

echo "Optimal cost found: $cost\n";

Note

Default value for cost is 10.

Learn more #learn-more

Comments #comments