rfc:improve_hash_hkdf_parameter
Differences
This shows you the differences between two versions of the page.
rfc:improve_hash_hkdf_parameter [2017/03/08 23:43] – yohgaki | rfc:improve_hash_hkdf_parameter [2017/09/22 13:28] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 2: | Line 2: | ||
* Version: 1.0 | * Version: 1.0 | ||
* Create Date: 2017-02-05 | * Create Date: 2017-02-05 | ||
- | * Discussion Start: 2017-02-13 | + | * Discussion Start: 2017-03-26 |
* Author: Yasuo Ohgaki < | * Author: Yasuo Ohgaki < | ||
- | * Status: | + | * Status: |
* First Published at: http:// | * First Published at: http:// | ||
===== Introduction ===== | ===== Introduction ===== | ||
- | HKDF (HMAC based KDF) is [[https://en.wikipedia.org/ | + | Even cryptographic hashes have secret information disclosure/analysis risks with string concatenations. For example, following code is weak (could be more vulnerable). |
- | In short, HKDF is a general purpose | + | Example 1: |
+ | <code php> | ||
+ | $new_key = hash(' | ||
+ | </ | ||
- | TL; | + | To reduce this risk, HMAC was invented. HMAC is known to be more secure compare to previous example. |
- | Please read "[[# | + | Example 2: |
+ | <code php> | ||
+ | $new_key = hash_hmac(' | ||
+ | </ | ||
+ | |||
+ | Note that HMAC divides keys as distinct parameters for better security. | ||
+ | |||
+ | When deriving new keys, there are many cases that developers need additional application- and context-specific information such as a protocol number, algorithm identifiers, | ||
+ | |||
+ | Example 3: | ||
+ | <code php> | ||
+ | $new_key = hash_hmac(' | ||
+ | </ | ||
+ | |||
+ | To reduce risk, keys and additional information should be divided into separated parameters. | ||
+ | |||
+ | Example 4: | ||
+ | <code php> | ||
+ | // $proto_version, | ||
+ | $info = $proto_version . $algo . $user_id; | ||
+ | |||
+ | // $prk must be cryptographically strong to derive strong $new_key. | ||
+ | $prk = hash_hmac(' | ||
+ | |||
+ | // $prk is strong and $info is non-secret, therefore $new_key is secured. | ||
+ | $new_key = hash_hmac(' | ||
+ | </ | ||
+ | |||
+ | This is the basic HKDF (HMAC based Key Derivation Function) operation. HKDF additionally supports shorting/ | ||
+ | |||
+ | <code php> | ||
+ | string HKDF(string $hash_algo, string $secret_key, | ||
+ | </ | ||
+ | |||
+ | Newly introduced HKDF function (hash_hkdf) has different signature that is inconsistent with hash() and hash_hmac() functions even if hash_hkdf() is simple hash_hmac() extension. | ||
+ | |||
+ | ===== Proposal ===== | ||
+ | |||
+ | Change hash_hkdf() signature from | ||
+ | |||
+ | <code php> | ||
+ | string hash_hkdf(string $algo, string $ikm [, int $length = 0 [, string $info = '' | ||
+ | Return value: Binary hash value ONLY. | ||
+ | </ | ||
+ | * $algo: Hash algorithm. e.g. " | ||
+ | * $ikm: Secret or non secret Input Key Material. Some kind of key. e.g. Super secret master key, password, API key, etc. | ||
+ | * $length: Optional Output length. If omitted, default output size of specified hash function. | ||
+ | * $info: Optional Generated key context. e.g Protocol number, user ID, group ID, applicable URI, etc. | ||
+ | * $salt: Optional secret or non secret salt value. e.g Random value such as nonce, timestamp, etc. | ||
+ | |||
+ | to | ||
+ | |||
+ | <code php> | ||
+ | string hash_hkdf(string $algo, string $ikm, string $salt , string $info [, int $length = 0 [, bool $raw_output = FALSE]]) | ||
+ | Return value: HEX string hash value by default. | ||
+ | </ | ||
+ | * $salt: Required. Set empty string to use without salt. More precedence over $info because HKDF security depends on $salt or $ikm strength. | ||
+ | * $info: Required. Set empty string to use without info. Optional context but user should use hash_hmac() without $info. | ||
+ | * $length: Optional. Mostly needless unless users need key derivations for low level crypto operations. | ||
+ | * $raw_output: | ||
+ | |||
+ | Note: Only changed/ | ||
+ | |||
+ | |||
+ | === Short Rationale - security, parameter importance, hash_hmac() signature === | ||
+ | |||
+ | Insecure usage is easily possible with current signature. | ||
+ | <code php> | ||
+ | $key = hash_hkdf(' | ||
+ | $key = hash_hkdf(' | ||
+ | $key = hash_hkdf(' | ||
+ | </ | ||
+ | |||
+ | $salt is described as more important parameter than "info" in RFC 5869, and it recommends there should be appropriate $salt whenever it is possible. $info makes HKDF more valuable because simpler and faster hash_hmac(string $algo , string $data , string $key [, bool $raw_output = false ] ) could be used instead when $info could be omitted. hash_hkdf() could be viewed as hash_hmac() extension. (It is HMAC extension indeed) It should be better to have compatible signatures for API consistency. | ||
+ | |||
+ | i.e. | ||
+ | hash_hmac(), | ||
+ | <code php> | ||
+ | string hash_hmac(string $algo, string $data, string $key [, bool $raw_output = FALSE ]) | ||
+ | Return value: HEX string hash value by default. | ||
+ | </ | ||
+ | |||
+ | Compatible hash_hkdf() signature would be | ||
+ | <code php> | ||
+ | string hash_hkdf(string $algo, string $ikm, string $salt , string $info [, int $length = 0 [, bool $raw_output = FALSE ]]) | ||
+ | Return value: HEX string hash value by default. | ||
+ | </ | ||
+ | |||
+ | For these reasons, $salt and $info are made to required parameters and made return to HEX hash value by default. | ||
+ | |||
+ | |||
+ | === Rationale behind salt as required parameter === | ||
+ | |||
+ | * Salt is responsible for IKM and output key security. Other parameters are not. | ||
+ | * Salt is required as pre-shared key in most cases. Key parameter should have more precedence. | ||
+ | * Users should use salt always when it is possible as per the RFC. | ||
+ | * Must use strong salt if it is possible. | ||
+ | * Must use secret salt if it is possible. | ||
+ | * Must use strong secret salt when input key is weak. | ||
+ | * Omitting salt is usually a bad(weak) design. See ' | ||
+ | |||
+ | === Rationale behind info as required parameter === | ||
+ | |||
+ | * hash_hmac() could be used when info has no use. | ||
+ | * info has well defined purpose, derive key(s) | ||
+ | |||
+ | === Rationale behind changed return value === | ||
+ | |||
+ | * HEX string return value and " | ||
+ | * Most use cases with PHP will require string return values. | ||
+ | |||
+ | hash(' | ||
+ | |||
+ | ===== Detailed Rationale ===== | ||
+ | |||
+ | HKDF (HMAC based KDF) is [[https:// | ||
+ | |||
+ | In short, HKDF is a general purpose hash function that is designed to create new key(s) from certain key using cryptographic hash function and HMAC. However, newly introduced hash_hkdf() is optimized for very limited usage. | ||
== Terms == | == Terms == | ||
Line 166: | Line 286: | ||
* When key(s) must be unique, either IKM or salt must be unique. | * When key(s) must be unique, either IKM or salt must be unique. | ||
- | Although it may seem IKM and salt is interchangeable, | + | Although it may seem IKM and salt is interchangeable, |
==== hash_hkdf() behavior and other hash functions ==== | ==== hash_hkdf() behavior and other hash functions ==== | ||
Line 249: | Line 369: | ||
You may display URL(6) and send password(7) via email. | You may display URL(6) and send password(7) via email. | ||
- | Step2: Validating keys | + | Step2: Validating keys (Check expiration time before this procedure) |
- Ask and get user to enter password ($ikm) that is supposed to be generated by Step1. | - Ask and get user to enter password ($ikm) that is supposed to be generated by Step1. | ||
- Get salt and hk parameters in the URL. $salt, $hk | - Get salt and hk parameters in the URL. $salt, $hk | ||
Line 310: | Line 430: | ||
You can create expiration enabled URL for limited use with similar steps. This could be used to allow anonymous storage object access with relatively secure manner. Example is AWS S3 presigned URL. | You can create expiration enabled URL for limited use with similar steps. This could be used to allow anonymous storage object access with relatively secure manner. Example is AWS S3 presigned URL. | ||
- | |||
- | ===== Proposal ===== | ||
- | |||
- | Change hash_hkdf() signature from | ||
- | |||
- | <code php> | ||
- | string hash_hkdf(string $algo, string $ikm [, int $length = 0 [, string $info = '' | ||
- | Return value: Binary hash value ONLY. | ||
- | </ | ||
- | * $algo: Hash algorithm. e.g. " | ||
- | * $ikm: Secret or non secret Input Key Material. Some kind of key. e.g. Super secret master key, password, API key, etc. | ||
- | * $length: Optional Output length. If omitted, default output size of specified hash function. | ||
- | * $info: Optional Generated key context. e.g Protocol number, user ID, group ID, applicable URI, etc. | ||
- | * $salt: Optional secret or non secret salt value. e.g Random value such as nonce, timestamp, etc. | ||
- | |||
- | to | ||
- | |||
- | <code php> | ||
- | string hash_hkdf(string $algo, string $ikm, string $salt , string $info [, int $length = 0 [, bool $raw_output = FALSE]]) | ||
- | Return value: HEX string hash value by default. | ||
- | </ | ||
- | * $salt: Required. Set empty string to use without salt. More precedence over $info because HKDF security depends on $salt or $ikm strength. | ||
- | * $info: Required. Set empty string to use without salt. Optional context but user should use hash_hmac() without $info. | ||
- | * $length: Optional. Mostly needless unless users need key derivations for low level crypto operations. | ||
- | * $raw_output: | ||
- | |||
- | Note: Only changed/ | ||
- | |||
- | Insecure usage is easily possible with current signature. | ||
- | <code php> | ||
- | $key = hash_hkdf(' | ||
- | $key = hash_hkdf(' | ||
- | $key = hash_hkdf(' | ||
- | </ | ||
- | |||
- | $salt is described as more important parameter than " | ||
- | |||
- | i.e. | ||
- | hash_hmac(), | ||
- | <code php> | ||
- | string hash_hmac(string $algo, string $data, string $key [, bool $raw_output = FALSE ]) | ||
- | Return value: HEX string hash value by default. | ||
- | </ | ||
- | |||
- | Compatible hash_hkdf() signature would be | ||
- | <code php> | ||
- | string hash_hkdf(string $algo, string $ikm, string $salt , string $info [, int $length = 0 [, bool $raw_output = FALSE ]]) | ||
- | Return value: HEX string hash value by default. | ||
- | </ | ||
- | |||
- | For these reasons, $salt and $info are made to required parameters and made return to HEX hash value by default. | ||
- | |||
- | |||
- | === Rationale behind salt as required parameter === | ||
- | |||
- | * Salt is responsible for IKM and output key security. Other parameters are not. | ||
- | * Salt is required as pre-shared key in most cases. Key parameter should have more precedence. | ||
- | * Users should use salt always when it is possible as per the RFC. | ||
- | * Must use strong salt if it is possible. | ||
- | * Must use secret salt if it is possible. | ||
- | * Must use strong secret salt when input key is weak. | ||
- | * Omitting salt is usually a bad(weak) design. See ' | ||
- | |||
- | === Rationale behind info as required parameter === | ||
- | |||
- | * hash_hmac() could be used when info has no use. | ||
- | * info has well defined purpose, derive key(s) for specific context by non secret information. | ||
- | |||
- | === Rationale behind changed return value === | ||
- | |||
- | * HEX string return value and " | ||
- | * Most use cases with PHP will require string return values. | ||
- | |||
- | hash(' | ||
===== Discussions ===== | ===== Discussions ===== | ||
Line 619: | Line 665: | ||
===== Backward Incompatible Changes ===== | ===== Backward Incompatible Changes ===== | ||
- | None. hash_hkdf() | + | It is merged into PHP 7.1.2. |
===== Proposed PHP Version(s) ===== | ===== Proposed PHP Version(s) ===== | ||
- | Next PHP 7.x | + | Next PHP 7.x and 7.1.x |
===== RFC Impact ===== | ===== RFC Impact ===== | ||
- | None. | + | PHP 7.1.2/7.1.3 has hash_hkdf(). |
===== Open Issues ===== | ===== Open Issues ===== | ||
Line 635: | Line 681: | ||
===== Unaffected PHP Functionality ===== | ===== Unaffected PHP Functionality ===== | ||
- | Nothing is affected. | + | Other than hash_hkdf() |
===== Future Scope ===== | ===== Future Scope ===== | ||
Line 644: | Line 690: | ||
State whether this project requires a 2/3 | State whether this project requires a 2/3 | ||
+ | <doodle title=" | ||
+ | * Yes | ||
+ | * No | ||
+ | </ | ||
+ | Vote start: 2017-03-26 | ||
+ | Vote end: 2017-04-07 UTC 23:59:59 | ||
===== Patches and Tests ===== | ===== Patches and Tests ===== |
rfc/improve_hash_hkdf_parameter.1489016608.txt.gz · Last modified: 2017/09/22 13:28 (external edit)