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.
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-argon2for 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 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.
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_WARNINGfor values that cannot be used as options for thePASSWORD_ARGON2Ialgorithm.
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.
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.
Subscribe to this blog via RSS.
Endings and Beginnings: Goodbye, and Please Welcome the Laminas Project!
2020-01-24