This is an old revision of the document!
PHP RFC: Argon2 Password Hash
Argon2, the recommended password hashing algorithm by the Password Hashing Competition, is a modern algorithm for securely hashing passwords. Argon2 addresses several key downsides of existing algorithms in that it is designed for the highest memory filling rate, and effective use multiple computing units while still providing defense against tradeoff attacks. Unlike Bcrypt, which just takes a single cost factor, Argon2 is parameterized by three distinct factors:
- A memory cost that defines memory usage of the algorithm
- A time cost that defines the execution time of the algorithm and the number of iterations
- And a parallelism factor, which defines the number of parallel threads
Argon2 comes in two distinct flavors, Argon2i and Argon2d. Argon2i which is optimized for password hashing and password based key derivation. Argon2 is faster and uses data-dependent memory access, making it highly resistant against GPU cracking attacks and suitable for applications with no threats from side-channel timing attacks (such as cryptocurrencies).
The existing password_* functions provided a forward compatible, simplified interface for hashing passwords. This RFC proposes the implementation for the Argon2 library (v1.3) within the password_* functions for use as a secure alternative to Bcrypt.
Proposed PHP Version(s)
Add Argon2 (v1.3) support in the next PHP 7.x (7.2) via –with-argon2. In PHP 7.4, make Argon2 the default PASSWORD_DEFAULT hashing algorithm.
This change introduces 2 new hashing algorithm constants
Similar to how PASSWORD_DEFAULT is an alias to PASSWORD_BCRYPT, a separate alias, PASSWORD_ARGON2 is introduced as an alias to PASSWORD_ARGON2I to simplify user land selection of the Argon2 hashing algorithm.
Additionally, 3 new default constants are introduced which define the default cost factors used by the algorithm.
PASSWORD_ARGON2_DEFAULT_MEMORY_COST PASSWORD_ARGON2_DEFAULT_TIME_COST PASSWORD_ARGON2_DEFAULT_THREADS
When using Argon2, a memory cost, time cost, and parallelism degree are required. Based upon a thorough examination of the specification, and review of existing Argon2 extensions for other languages, the following default cost factors are proposed.
m_cost = 64 Mib t_cost = 3 threads = 1
Changes to password_hash()
The password_hash() function is altered to accept both PASSWORD_ARGON2I and PASSWORD_ARGON2D as the algorithm, and accept the memory cost, time cost, and parallelism degree as options. When using Argon2. The following examples illustrate the new functionality.
// Argon2i with default cost factors password_hash('password', PASSWORD_ARGON2); // Argon2i by name with custom cost factors password_hash('password', PASSWORD_ARGON2I, ['m_cost' => 1<<17, 't_cost' => 4, 'threads' => 2]); // Argon2d by name with custom cost factors password_hash('password', PASSWORD_ARGON2I, ['m_cost' => 1<<4, 't_cost' => 2, 'threads' => 1]);
The new options for the algorithm are listed as follows. Each option is optional, and will use the listed defaults if not set.
$options = [ 'm_cost' => PASSWORD_ARGON2_DEFAULT_MEMORY_COST, 't_cost' => PASSWORD_ARGON2_DEFAULT_TIME_COST, 'threads' => PASSWORD_ARGON2_DEFAULT_THREADS ];
While deprecated within password_hash(), a 16 byte salt can also be provided. If not provided a 16 byte salt will be generated.
- E_WARNING: Memory cost is outside of allowed memory range
- E_WARNING: Time cost is outside of allowed time range
- E_WARNING: Invalid number of threads
Changes to password_verify()
The password_verify() function is altered return true or false if an Argon2 hash is specified. There are no API level changes to this function.
Changes to password_get_info()
The password_get_info() function is altered to accept Argon2 hashes, and to return information about a given Argon2 hash.
Changes to password_needs_rehash()
The password_get_info() function is altered to accept Argon2 hashes. If any of the cost factors are changed for an Argon2 hash, this function will return true.
$hash = password_hash('password', PASSWORD_ARGON2); password_needs_rehash($hash, PASSWORD_ARGON2); // false password_needs_rehash($hash, PASSWORD_ARGON2, ['m_cost' => 1<<17]); // true
Argon2 support is provided by passing –with-argon2[=DIR] to the configure script. A directory to the Argon2 build directory may be provided. If not provided, the library will search the OS for libargon2. If –with-argon2 is provided, configuration will fail if Argon2 cannot be found.
Windows deps should be updated to include a statically compile Argon2Ref.lib from the Argon2 reference library for proper linking.
Backward Incompatible Changes
[Resolved] Availability of libargon2
libargon2 is not yet wildly available in package managers yet. Any implementation in PHP will require manual compilation of the library. Per the discussion on https://github.com/php/php-src/pull/1997, this feature will be optionally available via the –with-argon2 configure flag.
If PHP is not compiled with –with-argon2, use of the features outlined in this RFC will not be available.
Proposed Voting Choices
Vote YES to include Argon2 as an alternative to Bcrypt within the password_* functions in 7.2, and to make PASSWORD_ARGON2 the default password hashing algorithm in 7.4. A 50%+1 majority should be sufficient.
Voting will be open for 1 week.
Patches and Tests
A working patch is available at: https://github.com/php/php-src/pull/1997
After the project is implemented, this section should contain
- the version(s) it was merged to
- a link to the git commit(s)
- a link to the PHP manual entry for the feature
- 2016-07-10: 0.1 Initial RFC draft
- 2016-07-10: 0.2 Adding pthread and linking issue
- 2016-07-11: 0.3 –with-argon2 flag added
- 2016-07-18: 0.3 Discussion opened
- 2016-08-01: 0.4 Voting opened