Hướng dẫn argon2 in php

2017-08-17 | By: Enrico Zimuel

PHP 7.2 will be released later this year (2017). This version contains some interesting additions, including two new security features: support of the Argon2 password hash algorithm, and the ext/sodium extension wrapping the libsodium library.

With these new features, PHP is the first programming language to adopt modern cryptography in its standard library.

In this article, we demonstrate the usage of the Argon2 password hash algorithm.

Installation of PHP 7.2

If you are reading this article before the general availability of 7.2, you need to compile PHP to use that version. You can download the source code from the PHP downloads site. Today, 17 August 2017, the most recent available version is 7.2.0 Beta 3 (file php-7.2.0beta3.tar.gz).

Before compiling PHP, you need to install the argon2 library. If you are using a Debian/Ubuntu Linux distribution, you can run the following command:

sudo apt install argon2 libargon2-0 libargon2-0-dev

To compile PHP, you need to extract the previous source code in a folder and run the following commands:

./configure --with-password-argon2
make
make install

Please note the usage of the option --with-password-argon2 for including support for the Argon2 algorithm.

This will install PHP 7.2 as the default PHP on your system. If you do not want to change the default PHP, you can omit the execution of the last command make install, or use the --prefix option to configure to specify an alternate location. In each of these cases, you will need to reference PHP 7.2 using the path of the folder installation.

Argon2

Argon2 is a password-based key derivation function winner of the Password Hashing Competition in July 2015.

This function is an evolution of the bcrypt and scrypt algorithms.

Argon2 provides security against brute force attacks using a predefined memory size, CPU time, and a degree of parallelism to prevent GPU attacks.

It uses 3 parameters that control the memory requirements, the execution time, and the parallelism level.

There are two main versions of this algorithm: Argon2i and Argon2d. Argon2i is the safest against side-channel attacks, while Argon2d provides the highest resistance against GPU cracking attacks.

Argon2d is not suitable for password hashing and should not be used.

PHP 7.2 adds Argon2i support to its Password Hashing Functions.

Usage of Argon2i in PHP

Argon2 support in PHP was proposed by Charles R. Portwood II in via an RFC.

The implemented algorithm in PHP is Argon2i (v1.3), and it can be provided via the $algo parameter to the password_hash() function. The signature of password_hash() is as follows:

password_hash( string $password , integer $algo [, array $options ]) : string

The second parameter ($algo) specifies the algorithm to use when hashing; the Argon2i algorithm is represented by the constant PASSWORD_ARGON2I.

As an example:

$password = 'test';
$hash = password_hash($password, PASSWORD_ARGON2I);
var_dump($hash);

The $hash result will contains a string of 98 characters as follows:

$argon2i$v=19$m=1024,t=2,p=2$TmxLemFoVnZFaEJuT1NyYg$4j2ZFDn1fVS70ZExmlJ33rXOinafcBXrp6A6grHEPkI

This string contains sub-string of parts, separated by dollar ($). These parts are:

argon2i
v=19
m=1024,t=2,p=2
TmxLemFoVnZFaEJuT1NyYg
4j2ZFDn1fVS70ZExmlJ33rXOinafcBXrp6A6grHEPkI

The first part is the algorithm name (argon2i), the second is the Argon2i version, and the third part is a list of algorithm parameters related to memory cost (in Kb), time cost, and threads to be used (parallelism).

The fourth parameter is the random salt value, encoded in Base64. This value is generated by password_hash() using a random value for each execution. This is why we have different hash outputs for the same input string. The default size of the salt is 16 bytes.

The fifth and last parameter of the string contains the hash value, encoded in Base64. The hash size is 32 bytes.

PHP provides a function named password_get_info($hash) to get information about the hash generated by password_hash(). For instance, if you use password_get_info() on the previous value, you will receive:

array(3) {
  ["algo"]=>
  int(2)
  ["algoName"]=>
  string(7) "argon2i"
  ["options"]=>
  array(3) {
    ["memory_cost"]=>
    int(1024)
    ["time_cost"]=>
    int(2)
    ["threads"]=>
    int(2)
  }
}

The default parameters for the algorithm are a memory_cost of 1024 Kb (1 Mb), a time_cost of 2, and two threads to be used for parallelism. The Argon2 specifications suggest to use a power of 2 value for the memory_cost.

These values can be changed using the $options parameter of the password_hash() function. As an example:

$password = 'test';
$options = [
    'memory_cost' => 1<<17, // 128 Mb
    'time_cost'   => 4,
    'threads'     => 3,
];
$hash = password_hash($password, PASSWORD_ARGON2I, $options);
var_dump($hash);

PHP will generate an E_WARNING for values that cannot be used as options for the PASSWORD_ARGON2I algorithm.

Regarding the default option values, we suggest to change it according to the use cases and CPU + RAM available. From the PHP RFC:

Due to the variety of platforms PHP runs on, the cost factors are deliberately set low as to not accidentally exhaust system resources on shared or low resource systems when using the default cost parameters. Consequently, users should adjust the cost factors to match the system they're working on. As Argon2 doesn't have any "bad" values, however consuming more resources is considered better than consuming less. Users are encouraged to adjust the cost factors for the platform they're developing for.

Conclusion

In this article we demonstrated usager of the Argon2 password hash algorithm with PHP 7.2. The Argon2 algorithm is the state of the art for password protection and it can be now used in PHP without installing additional extensions. This is a very nice security feature that will improve the security of PHP applications that store user passwords. In a future article, we will cover the Sodium extension, another new security feature included in PHP 7.2. With these new features, PHP is the first language to support modern cryptography in the core of the language.

SHARE: