Reference

In This Article

Password

In the Zend\Crypt\Password namespace you will find a number of password formats supported by the zend-crypt component. These currently include:

  • bcrypt
  • Apache (htpasswd)

If you need to choose a password format to store a user’s password, we suggest using the bcrypt algorithm, as it is considered secure against brute forcing attacks (see details below).

Bcrypt

The bcrypt algorithm is a hashing algorithm that is widely used and recommended by the security community to store user passwords in a secure way.

Classic hashing mechanisms like MD5 or SHA, with or without a salt value, are not considered secure anymore (read this post to understand why).

The security of bcrypt is related to the speed of the algorithm. Bcrypt is very slow, and can take up to a second to generate a hash value. That means a brute force attack is impossible to execute, due to the amount of time that required.

Bcrypt uses a cost parameter that specify the number of cycles to use in the algorithm. Increasing this number the algorithm will spend more time to generate the hash output. The cost parameter is represented by an integer value between 4 to 31. The default cost value of Zend\Crypt\Password\Bcrypt is 10, requiring around 0.07s using a CPU Intel i5 at 3.3Ghz (the cost parameter is a relative value according to the speed of the CPU used). Starting with version 2.3.0, we changed the default value of the cost parameter from 14 to 10, in an effort to reduce denial-of-service attacks due to too high computational time requirements. (Read this article on aggressive password stretching for more information).

If you want to change the cost parameter of the bcrypt algorithm, you can use the setCost() method. Please note, if you change the cost parameter, the resulting hash will be different. However, This will not affect the verification process of the algorithm, therefore not breaking the password hashes you already have stored; Bcrypt reads the cost parameter from the hash value during password authentication. All of the parts needed to verify the hash are present in the hash itself,, separated with $’s; first the algorithm, then the cost, the salt, and then finally the hash.

The example below demonstrates using the bcrypt algorithm to store a user’s password:

use Zend\Crypt\Password\Bcrypt;

$bcrypt = new Bcrypt();
$securePass = $bcrypt->create('user password');

The output of the create() method is the hash of the password. This value can then be stored in a repository like a database (the output is a string of 60 bytes).

Bcrypt truncates Input > 72 bytes

The input string of the bcrypt algorithm is limited to 72 bytes. If you use a string with a length more than this limit, bcrypt will consider only the first 72 bytes. If you need to use a longer string, you should pre-hash it. We provide the class Zend\Crypt\Password\BcryptSha for performing password pre-hashing of hash input > 72 bytes.

To verify if a given password is valid against a bcrypt value you can use the verify() method. The example below demonstrates verification:

use Zend\Crypt\Password\Bcrypt;

$bcrypt = new Bcrypt();
$securePass = 'the stored bcrypt value';
$password = 'the password to check';

if ($bcrypt->verify($password, $securePass)) {
    echo "The password is correct! \n";
} else {
    echo "The password is NOT correct.\n";
}

Bcrypt also uses a salt value to improve the randomness of the algorithm. By default, Zend\Crypt\Password\Bcrypt generates a random salt for each hash. If you want to specify a preselected salt you can use the setSalt() method.

We also provide a getSalt() method to retrieve the salt specified by the user. The salt and the cost parameter can be also specified during the constructor of the class, as demonstrated below:

use Zend\Crypt\Password\Bcrypt;

$bcrypt = new Bcrypt([
    'salt' => 'random value',
    'cost' => 11
]);

Version 3.0

Starting with version 3.0, we now use the password_hash() and `password_verify() functions introduced in PHP 5.5 to generate bcrypt hash values. We provide backwards compatibility tests to ensure that any hashes generated with version 2 releases can still be validated under version 3.

Apache

Zend\Crypt\Password\Apache supports all the password formats used by Apache (htpasswd). These formats include:

  • CRYPT, which uses the traditional Unix crypt(3) function with a randomly-generated 32-bit salt (only 12 bits used) and the first 8 characters of the password;
  • SHA1, “{SHA}” + Base64-encoded SHA-1 digest of the password;
  • MD5, “$apr1$” + the result of an Apache-specific algorithm using an iterated (1,000 times) MD5 digest of various combinations of a random 32-bit salt and the password.
  • Digest, the MD5 hash of the string user:realm:password as a 32-character string of hexadecimal digits. realm is the Authorization Realm argument to the AuthName directive in httpd.conf.

In order to specify the format of the Apache’s password, use the setFormat() method. An example with all the formats usage is demonstrated below:

use Zend\Crypt\Password\Apache;

$apache = new Apache();

$apache->setFormat('crypt');
printf ("CRYPT output: %s\n", $apache->create('password'));

$apache->setFormat('sha1');
printf ("SHA1 output: %s\n", $apache->create('password'));

$apache->setFormat('md5');
printf ("MD5 output: %s\n", $apache->create('password'));

$apache->setFormat('digest');
$apache->setUserName('enrico');
$apache->setAuthName('test');
printf ("Digest output: %s\n", $apache->create('password'));

You can also specify the format of the password during the constructor of the class:

use Zend\Crypt\Password\Apache;

$apache = new Apache([
    'format' => 'md5'
]);

Other possible parameters to pass in the constructor are username and authname, for the digest format.

Found a mistake or want to contribute to the documentation? Edit this page on GitHub!