rfc:argon2_password_hash

This is an old revision of the document!


PHP RFC: Argon2 Password Hash

Introduction

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:

  1. A memory cost that defines memory usage of the algorithm
  2. A time cost that defines the execution time of the algorithm and the number of iterations
  3. 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).

Proposal

The existing password_* functions provided a forward compatible, simplified interface for hashing passwords. This RFC proposes the implementation of Argon2i (v1.3) within the password_* functions for use as a secure alternative to Bcrypt.

Proposed PHP Version(s)

Add Argon2i (v1.3) support in the next PHP 7.x (7.2) via --with-password-argon2.

New Constants

This change introduces a new hashing algorithm constant

PASSWORD_ARGON2I

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.

PASSWORD_ARGON2

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

Cost Factors

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 either PASSWORD_ARGON2 or PASSWORD_ARGON2I 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]);

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.

Errors:

  1. E_WARNING: Memory cost is outside of allowed memory range
  2. E_WARNING: Time cost is outside of allowed time range
  3. 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.

var_dump(password_get_info('$argon2i$v=19$m=65536,t=3,p=1$SWhIcG5MT21Pc01PbWdVZw$WagZELICsz7jlqOR2YzoEVTWb2oOX1tYdnhZYXxptbU'));
 
array(3) {
  ["algo"]=>
  int(3)
  ["algoName"]=>
  string(7) "argon2i"
  ["options"]=>
  array(3) {
    ["m_cost"]=>
    int(65536)
    ["t_cost"]=>
    int(3)
    ["threads"]=>
    int(1)
  }
}

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

Configure Flag

Argon2 support is provided by passing --with-password-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-password-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

None.

Open Issues

Cost options

The current cost options are derived from recommendations from the Argon2 developers, and comparison to other Argon2 implementations in other languages. The default options however could be set to the developers minimum recommended values without any loss of security.

m_cost = 16
t_cost = 2
threads = 1

While the spec outlines there are no “insecure” values for these attributes, shipping with stronger default values could be better for the long term.

Providing default options

Providing default options allows for ease of use, and encourages use. Not providing options encourages experimentation on your system, but discourages use from people unfamiliar with the algorithm.

PASSWORD_ARGON2 or PASSWORD_ARGON2I

The library exposes PASSWORD_ARGON2I, and PASSWORD_ARGON2 as an alias to PASSWORD_ARGON2I. As only Argon2i is made available, two constants is unnecessary.

[Resolved] Inclusion of Argon2d

Argon2i is suitable for password hashing. While Argon2d has other uses, it is not suitable for password hashing. A recommendation is to remove Argon2d to keep the feature in line with the intent of password_hash being a simple hashing function.

The password_* functions should be strictly related to password hashing behaviors, and their scope should not extend to general hashing. Consequently this RFC now only proposes the implementation of Argon2i within password_*. Argon2d will not be implemented as it is not suitable for password hashing, despite how simple it would be to include it within the password_* functions.

[Resolved] Configure Flag

A discussion on internals proposes --with-password-argon2 is more suitable than --with-argon2 as this is a sub-feature rather than a full feature implementation of the entire Argon2 library.

--with-argon2 implies full inclusion of the Argon2 library. Since only Argon2i is implemented within password_*, the configure argument should reflect that.

[Resolved] Inclusion on 7.4

Per discussion on the internals mailing list during an initial vote, this RFC no longer proposes changes to PASSWORD_DEFAULT in 7.4.

[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-password-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. A 50%+1 majority should be sufficient.

Voting will be open for 1 week.

argon2_password_hash_revote
Real name Yes No
colinodell (colinodell)  
daverandom (daverandom)  
davey (davey)  
galvao (galvao)  
guilhermeblanco (guilhermeblanco)  
kalle (kalle)  
leigh (leigh)  
lstrojny (lstrojny)  
mariano (mariano)  
nikic (nikic)  
trowski (trowski)  
yohgaki (yohgaki)  
Count: 12 0

Patches and Tests

A working patch is available at: https://github.com/php/php-src/pull/1997

Implementation

After the project is implemented, this section should contain

  1. the version(s) it was merged to
  2. a link to the git commit(s)
  3. a link to the PHP manual entry for the feature

References

Changelog

  1. 2016-07-10: 0.1 Initial RFC draft
  2. 2016-07-10: 0.2 Adding pthread and linking issue
  3. 2016-07-11: 0.3 --with-argon2 flag added
  4. 2016-07-18: 0.3 Discussion opened
  5. 2016-08-01: 0.4 Voting opened
  6. 2016-08-01: 0.5 Voting closes due to issue with RFC, removing 7.4 and adding new issues brought up during vote
  7. 2016-08-01: 0.6 Removing Argon2 from password_*, changing configure flag to --with-password-argon2 for clarity of scope
rfc/argon2_password_hash.1470408973.txt.gz · Last modified: 2017/09/22 13:28 (external edit)