rfc:argon2_password_hash_enhancements

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:argon2_password_hash_enhancements [2018/01/11 17:51] charlesportwoodiirfc:argon2_password_hash_enhancements [2018/10/10 11:17] (current) – typo: IETF neufeind
Line 1: Line 1:
 ====== PHP RFC: Argon2 Password Hash Enhancements ====== ====== PHP RFC: Argon2 Password Hash Enhancements ======
-  * Version: 0.1+  * Version: 0.2
   * Date: 2018-01-11   * Date: 2018-01-11
   * Author: Charles R. Portwood II <charlesportwoodii@erianna.com>   * Author: Charles R. Portwood II <charlesportwoodii@erianna.com>
-  * Status: Draft+  * Status: Implemented (PHP 7.3)
   * First Published at: http://wiki.php.net/rfc/argon2_password_hash_enhancements   * First Published at: http://wiki.php.net/rfc/argon2_password_hash_enhancements
  
Line 10: Line 10:
  
 ==== Overview of Argon2 and Argon2id specific algorithm ==== ==== Overview of Argon2 and Argon2id specific algorithm ====
-Argon2 has one primary variant: Argon2id, and two supplementary variants: Argon2d and Argon2i. Argon2d uses data-depending memory access, which makes it suitable for cryptocurrencies and proof-of-work applications with no threats from side-channel timing attacks. Argon2i uses data-independent memory access, which is preferred for password hashing and password-based key derivation. Argon2id works as Argon2i for the first half of the first iteration over the memory, and as Argon2d for the rest, thus providing both side-channel attack protection and brute-force cost savings due to time-memory tradeoffs. Argon2i makes more passes over the memory to protect from tradeoff attacks. 
  
 +Argon2 has three variants: Argon2i, Argon2d, and Argon2id. Argon2d is faster and uses data-depending memory access, which makes it highly resistant against GPU cracking attacks and suitable for applications with no threats from side-channel timing attacks (eg. cryptocurrencies). Argon2i instead uses data-independent memory access, which is preferred for password hashing and password-based key derivation, but it is slower as it makes more passes over the memory to protect from tradeoff attacks. Argon2id is a hybrid of Argon2i and Argon2d, using a combination of data-depending and data-independent memory accesses, which gives some of Argon2i's resistance to side-channel cache timing attacks and much of Argon2d's resistance to GPU cracking attacks.
  
-Argon2id is now the recommended Argon2 variant to use in the ITEF draft spec.+ 
 +Argon2id is now the recommended Argon2 variant to use in the IETF draft spec.
  
 ===== Proposal ===== ===== Proposal =====
Line 30: Line 31:
  
 ==== Changes to password_hash() ==== ==== Changes to password_hash() ====
-The password_hash() function is altered to accept either PASSWORD_ARGON2ID as the algorithm.+The password_hash() function is altered to accept PASSWORD_ARGON2ID as the algorithm.
  
 <code php> <code php>
Line 37: Line 38:
 </code> </code>
  
-Behaviorally, this implementation will act identical to the Argon2i implementation in that it will accept the same cost variables introduces in the Argon2i RFC.+This implementation will act identical to the Argon2i implementation in that it will accept the same cost variables introduces in the Argon2i RFC.
  
 <code php> <code php>
-// Argon2id by name with custom cost factors+// Argon2id by name with custom cost factors behaves the same as PASSWORD_ARGON2I
 password_hash('password', PASSWORD_ARGON2ID, ['memory_cost' => 1<<17, 'time_cost' => 4, 'threads' => 2]); password_hash('password', PASSWORD_ARGON2ID, ['memory_cost' => 1<<17, 'time_cost' => 4, 'threads' => 2]);
 </code> </code>
  
-No additional changes to this method are anticipated.+Argon2id will use the same default cost measures as the Argon2i implementation.
  
 ==== Changes to password_verify() ==== ==== Changes to password_verify() ====
-The password_verify() function is altered return true or false if an Argon2id hash is specified. There are no API level changes to this function.+The password_verify() function work with Argon2id in addition to Argon2i
  
 ==== Changes to password_get_info() ==== ==== Changes to password_get_info() ====
Line 53: Line 54:
  
 <code php> <code php>
-var_dump(password_get_info('$argon2id$v=19$m=65536,t=3,p=1$SWhIcG5MT21Pc01PbWdVZw$WagZELICsz7jlqOR2YzoEVTWb2oOX1tYdnhZYXxptbU'));+var_dump(password_get_info('$argon2id$v=19$m=1024,t=2,p=2$ZUhOUVczSHpZRDBDU2ZBRA$k/vI1wKP4s0ecJIpUybRfgBeo3as1PhIV1Od6PvOEFA'));
  
 array(3) { array(3) {
Line 59: Line 60:
   int(3)   int(3)
   ["algoName"]=>   ["algoName"]=>
-  string(7) "argon2id"+  string(8) "argon2id"
   ["options"]=>   ["options"]=>
   array(3) {   array(3) {
     ["memory_cost"]=>     ["memory_cost"]=>
-    int(65536)+    int(1024)
     ["time_cost"]=>     ["time_cost"]=>
-    int(3)+    int(2)
     ["threads"]=>     ["threads"]=>
-    int(1)+    int(2)
   }   }
 } }
Line 80: Line 81:
 password_needs_rehash($hash, PASSWORD_ARGON2ID, ['memory_cost' => 1<<17]); // true password_needs_rehash($hash, PASSWORD_ARGON2ID, ['memory_cost' => 1<<17]); // true
 </code> </code>
 +
 +===== Configure/m4 Changes =====
 +
 +Argon2id is only available in reference library >= 20161029. As a result of this change, the --with-password-argon2[=dir] option will include support for both Argon2i and Argon2id. Configure will fail if libargon2 is < 20161029.
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
Line 86: Line 91:
 ===== Discussion Issues ===== ===== Discussion Issues =====
  
-==== Why was Argon2id not included in the original RFC? ====+==== Why was Argon2id not included in the original RFC? [CLOSED] ====
  
-The original Argon2i password_hash RFC https://wiki.php.net/rfc/argon2_password_hash was created before Argon2id draft spec was complete or made available. Argon2id was not introduced into the reference library until after the original RFC was voted on, approved, and merged into PHP 7.2 (20161029). To avoid a re-vote and re-implementation of the merge request Argon2id was not included in the original RFC.+The original Argon2i password_hash RFC https://wiki.php.net/rfc/argon2_password_hash was created before Argon2id draft spec was complete or made available. When the original RFC was introducedonly Argon2i and Argon2d existed.
  
-That being said, a late addition to the implementation include support for reference library 20161029 since it changed the argon2_encoded() method. This change was made due to uncertainty about what reference library implementation would land in Debian/RHEL, and to ensure forward compatibility with the 20161029 library version if that was the version that would land in Debian/RHEL.+Argon2id was not introduced into the reference library until after the original RFC was voted on, approved, and merged into PHP 7.2. To avoid a re-vote and re-implementation of the merge request Argon2id was not included in the original Argon2i password_hash RFC.
  
 +That being said, a late addition to the implementation include support for reference library 20161029 since it changed the argon2_encoded() method. This change was made due to uncertainty about what reference library implementation would land in Debian Stretch/RHEL, and to ensure forward compatibility with the 20161029 library version if that was the version that would land in Debian/RHEL.
  
-==== Configuring // Support for Argon2 >= 20161029 ====+==== Should we deprecate Argon2i? [RESOLVED] ==== 
 + 
 +No, I do not believe we should deprecate Argon2i from password_*. Argon2i remains a perfectly secure and reasonable choice for password hashing. Argon2id simply provides better resistance to some form of attacks at the cost of time-memory tradeoffs. Argon2id is recommended at this point simply because it provides a blend of Argon2i and Argon2d. The existence of Argon2id does not negate the benefits of Argon2i. 
 + 
 +==== Add Secret Parameter? [RESOLVED] ==== 
 + 
 +Argon2 exposes via the _ctx API (which currently isn't used by this implementation) a way to inject a separate secret key, which can be used to further strength the resulting Argon2 hashes. 
 + 
 +There has been some discussion of this both within bugs.php.net (https://bugs.php.net/bug.php?id=75388) and within the reference library (https://github.com/P-H-C/phc-winner-argon2/issues/222). 
 + 
 +I do not feel including the secret parameter within the password_hashing API is appropriate for the following reasons: 
 +  - Per the Argon2 documentation, the secret key is intended for keyed hashing. Introducing the secret key parameter adds complexity to the password_hash API. The primary purpose of the password_hash API, per the original spec is to be a //simple// hashing tool. Adding the secret key would require significant documentation about what constitutes a secret key, and at minimum provide detailed documentation on how to manage these keys, if not provide a key management solution. Key management is outside of the scope of the password_hash API, and thus should not be included. 
 +  - The Argon2 spec doesn't provide a way to re-key this secret should it change. This topic is discussed within the reference library: https://github.com/P-H-C/phc-winner-argon2/issues/222. As the developer is ultimately responsible for handling the re-keying aspect, and as the reference library may one day include the ability to easily re-key, I do not find it appropriate for us to include this functionality at this time. This topic may be suitable for review in the future. 
 +  - More complex behaviors are available in Libsodium (which is now a core PHP extension). 
 + 
 +==== Custom Salt Value? [RESOLVED] ==== 
 + 
 +The salt option was deprecated from password_hash in 7.0. I do not feel it is appropriate to re-introduce it again. Moreover, the addition of a custom salt attribute was rejected in the original Argon2i RFC. 
 + 
 +==== Configuring // Support for Argon2 >= 20161029 [RESOLVED] ====
  
 Argon2id is only available in reference library >= 20161029.  Argon2id is only available in reference library >= 20161029. 
Line 101: Line 126:
 PHP already knows if Argon2id is available when compiling PHP. As Argon2id is a //new// algorithm however, we need to decide how --with-password-argon2[=DIR] should behave. Should it include both Argon2i and Argon2id? Should we force a minimum reference library version? Or should we introduce a new configure flag for this new function? PHP already knows if Argon2id is available when compiling PHP. As Argon2id is a //new// algorithm however, we need to decide how --with-password-argon2[=DIR] should behave. Should it include both Argon2i and Argon2id? Should we force a minimum reference library version? Or should we introduce a new configure flag for this new function?
  
-=== Force lib >= 20161029, --with-password-argon2 is inclusive of both Argon2i and Argon2id ===+This RFC proposes the first option, of forcing lib >= 20161029 during the configure stage making the --with-password-argon2 flag inclusive of both Argon2i and Argon2id. 
 + 
 +=== Force lib >= 20161029, making the --with-password-argon2 flag inclusive of both Argon2i and Argon2id [RESOLVED] ===
  
 In this scenario we would force the library version to be >= 20161029. From configure, –with-password-argon2[=DIR] m4 would fail if Argon2id wasn't available, and prompt the user to upgrade their library version. The existing implementation already performs a check for the availability of Argon2id due to ABI differences with argon2_encoded() in different library version. In this scenario we would force the library version to be >= 20161029. From configure, –with-password-argon2[=DIR] m4 would fail if Argon2id wasn't available, and prompt the user to upgrade their library version. The existing implementation already performs a check for the availability of Argon2id due to ABI differences with argon2_encoded() in different library version.
  
-This change would be the easiest, and most forward thinking since Argon2id is the recommended ietf algorithm. Additionally it would ensure that PHP stays up to date with the reference library. +This change would be the easiest, and most forward thinking since Argon2id is the recommended ITEF algorithm. Additionally it would ensure that PHP stays up to date with the reference library.  
 + 
 +This would require users on Stretch however to manually compile and upgrade to lib >= 20161029. The affect on Windows users is minimal as we're already providing ref/lib's for Windows compilation. Buster (testing) and Sid (unstable) are scheduled with 20161029.
  
-This would require users on Stretch however to manually compile and upgrade to lib >= 20161029. The affect on Windows users is minimal as we're already providing ref/lib'for Windows compilation.+Additionally, it isn't uncommon for PHP to force minimum versions (cite OpenSSL, cURL) of library version.
  
 This is my recommended approach as it forces us to be conscious to changes in the Argon2 reference library. This is my recommended approach as it forces us to be conscious to changes in the Argon2 reference library.
  
-=== Allow --with-password-argon2[=DIR] to conditionally enable Argon2id based upon what's available in the library version. ===+=== Allow --with-password-argon2[=DIR] to conditionally enable Argon2id based upon what's available in the library version. [RESOLVED] ===
  
 As m4 already knows if Argon2id is available in the lib, the functionality in PHP would be enabled for Argon2id if and only if Argon2id was available in the library.  As m4 already knows if Argon2id is available in the lib, the functionality in PHP would be enabled for Argon2id if and only if Argon2id was available in the library. 
  
-This approach is the most robust, and provides the greatest amount of backwards comparability with the reference library, but may obscure what feature is actually enabled or not if the user isn'carefully watching the output of configureIn userland code users would have to perform a conditional check for if Argon2id or Argon2i is available, which may introduces confusion if different environments are compiled differently.+This approach is offered as a fallback in case option (1) is not selected. The greatest failings with this option are that user land checks would need to be performed for PASSWORD_ARGON2I and PASSWORD_ARGON2ID to determine what is actually available. Disabling certain features based upon a library version muddles what was actually available since phpinfo() doesn'report the compiled library versionBetween the user land checks and the inability to easily identify what features are actually available likely disqualify this option.
  
-I do not recommend this approach for the userland issue mentioned above.+This RFC does not propose this option.
  
-=== Introduce a new configure argument --with-password-argon2id ===+=== Introduce a new configure argument --with-password-argon2id [RESOLVED] ===
  
-This is awkwardbut we could explicitly use a new configure flag --with-password-argon2id to determine if Argon2id should be included within PHP. This flag would be in addition to --with-password-argon2. This behavior is award however. As a end user I would expected --with-password-argon2 is inclusive of any valid Argon2 algorithm. Moreover as the --with-password-argon2 check already determines if Argon2id is available, it may introduce more complexity than desired in the implementation. +A thirdless desirable solution would be to explicitly use a new configure flag --with-password-argon2id, and run the Argon2id checks only if this flag is declared. This flag would be in addition to --with-password-argon2.  As a end user I would expected --with-password-argon2 to be inclusive of any Argon2 algorithm. Moreover as the --with-password-argon2 check already determines if Argon2id is available, it may introduce more complexity than desired in the implementation. This is more visible than option (2) but still suffers from the same core problems.
- +
-This option is listed only to illustrate proof of thought and is not recommended.+
  
 +This RFC does not propose this option.
  
 ===== Proposed Voting Choices ===== ===== Proposed Voting Choices =====
  
-Vote YES to include Argon2id as an alternative to Argon2i within the password_* functions in 7.3. A 50%+1 majority should be sufficient.+Vote YES to include Argon2id as an alternative to Argon2i within the password_* functions in 7.3.
  
-Voting will be open for 2 weeks.+A 50%+1 majority should be sufficient. 
 + 
 +<doodle title="argon2_password_hash_enhancements" auth="charlesportwoodii" voteType="single" closed="true"> 
 +   * Yes 
 +   * No 
 +</doodle> 
 + 
 + 
 +Voting will be from 6/6/2018 to 6/18/2018.
  
 ===== Implementation ===== ===== Implementation =====
  
-The implementation is rather straightforward, however I am holding off an implementation until a discussion around the configure behavior is addressed.+The reference implementation assumes --with-password-argon2[=DIR] is inclusive of both Argon2i and Argon2id. At this time this is provided for reference purposes. 
 + 
 +  - https://github.com/php/php-src/compare/master...charlesportwoodii:argon2_password_hash_enhancements?expand=1 
 + 
 +===== Implementation =====
  
 +  - Github Merge Request: https://github.com/php/php-src/pull/3311
 +  - Merged into PHP: https://github.com/php/php-src/commit/55277a668409b9d62ac42695934aca64e354869f
 + 
 ===== References ===== ===== References =====
  
Line 141: Line 184:
   - https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf   - https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf
   - https://github.com/P-H-C/phc-winner-argon2   - https://github.com/P-H-C/phc-winner-argon2
-  - https://crypto.stackexchange.com/questions/48935/why-use-argon2i-or-argon2d-if-argon2id-exists +  - https://crypto.stackexchange.com/questions/48935/why-use-argon2i-or-argon2d-if-argon2id-exists[1] 
-  - https://tools.ietf.org/html/draft-irtf-cfrg-argon2-02+  - https://tools.ietf.org/html/draft-irtf-cfrg-argon2-03
   - https://bugs.php.net/bug.php?id=75224   - https://bugs.php.net/bug.php?id=75224
  
Line 148: Line 191:
  
   - 2018-01-11: 0.1 Initial RFC draft   - 2018-01-11: 0.1 Initial RFC draft
 +  - 2018-02-01: Opened discussion to internals
 +  - 2018-05-22: Re-submitted to internals for discussion
 +  - 2018-06-06: Opened for Vote
 +  - 2018-06-19: Accepted
 +  - 2018-06-21: Implemented
rfc/argon2_password_hash_enhancements.1515693109.txt.gz · Last modified: 2018/01/11 17:51 by charlesportwoodii