Newsgroups: php.doc,php.internals Path: news.php.net Xref: news.php.net php.doc:969386569 php.internals:98916 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 70969 invoked from network); 29 Apr 2017 23:15:15 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 29 Apr 2017 23:15:15 -0000 Authentication-Results: pb1.pair.com smtp.mail=yohgaki@ohgaki.net; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=yohgaki@ohgaki.net; sender-id=pass Received-SPF: pass (pb1.pair.com: domain ohgaki.net designates 180.42.98.130 as permitted sender) X-PHP-List-Original-Sender: yohgaki@ohgaki.net X-Host-Fingerprint: 180.42.98.130 ns1.es-i.jp Received: from [180.42.98.130] ([180.42.98.130:36170] helo=es-i.jp) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id F5/1B-01540-F7E15095 for ; Sat, 29 Apr 2017 19:15:13 -0400 Received: (qmail 37217 invoked by uid 89); 29 Apr 2017 23:15:07 -0000 Received: from unknown (HELO mail-qk0-f169.google.com) (yohgaki@ohgaki.net@209.85.220.169) by 0 with ESMTPA; 29 Apr 2017 23:15:07 -0000 Received: by mail-qk0-f169.google.com with SMTP id q1so1248703qkd.2; Sat, 29 Apr 2017 16:15:07 -0700 (PDT) X-Gm-Message-State: AN3rC/7iPLDrGS+BSGNMqoASH5jkpDXt6CB3p284l8N7IkAyV3NUeX7h eGaImZO+ByZYyTdn1/EbyXbsw/iMBQ== X-Received: by 10.55.104.66 with SMTP id d63mr7371258qkc.260.1493507701176; Sat, 29 Apr 2017 16:15:01 -0700 (PDT) MIME-Version: 1.0 Received: by 10.140.27.179 with HTTP; Sat, 29 Apr 2017 16:14:20 -0700 (PDT) In-Reply-To: References: <1924612862.1298112.1492071094545.JavaMail.zimbra@pieterhordijk.com> <690015854.1384408.1492163148986.JavaMail.zimbra@pieterhordijk.com> Date: Sun, 30 Apr 2017 08:14:20 +0900 X-Gmail-Original-Message-ID: Message-ID: To: Andrey Andreev Cc: Niklas Keller , Pieter Hordijk , Joe Watkins , internals , phpdoc , Nikita Popov Content-Type: multipart/alternative; boundary=94eb2c05bc82ff84b2054e565bc5 Subject: Re: [PHP-DEV] [RFC][VOTE] Improve hash_hkdf() parameter From: yohgaki@ohgaki.net (Yasuo Ohgaki) --94eb2c05bc82ff84b2054e565bc5 Content-Type: text/plain; charset=UTF-8 Hi Andrey, On Tue, Apr 25, 2017 at 7:17 PM, Andrey Andreev wrote: > Hi, > > On Tue, Apr 25, 2017 at 3:28 AM, Yasuo Ohgaki wrote: > >> > >> If you want examples, search GitHub for PHP code utilizing HKDF - you > >> will see that most projects use it without a salt, including > >> https://github.com/defuse/php-encryption - pretty much the best PHP > >> userspace crypto library today. And I'm only saying "most" because I > >> can't be bothered to go through literally all of them; I've found NONE > >> that do use the salt. > > > > > > Wrong. > > I don't think the author wouldn't make such mistake, so I checked. > > > > /** > > * Derives authentication and encryption keys from the secret, using > a > > slow > > * key derivation function if the secret is a password. > > * > > * @param string $salt > > * > > * @throws Ex\EnvironmentIsBrokenException > > * > > * @return DerivedKeys > > */ > > public function deriveKeys($salt) > > { > > if (Core::ourStrlen($salt) !== Core::SALT_BYTE_SIZE) { > > throw new Ex\EnvironmentIsBrokenException('Bad salt.'); > > } > > > > if ($this->secret_type === self::SECRET_TYPE_KEY) { > > $akey = Core::HKDF( > > Core::HASH_FUNCTION_NAME, > > $this->secret->getRawBytes(), > > Core::KEY_BYTE_SIZE, > > Core::AUTHENTICATION_INFO_STRING, > > $salt > > ); > > $ekey = Core::HKDF( > > Core::HASH_FUNCTION_NAME, > > $this->secret->getRawBytes(), > > Core::KEY_BYTE_SIZE, > > Core::ENCRYPTION_INFO_STRING, > > $salt > > ); > > return new DerivedKeys($akey, $ekey); > > } elseif ($this->secret_type === self::SECRET_TYPE_PASSWORD) { > > > > > > Fair enough, it uses a salt somewhere I didn't see - as I said, I > didn't check literally everything. > It doesn't use it here: > https://github.com/defuse/php-encryption/blob/ > 0364e3ea20d2382e709034e972d474f551c3273c/src/Crypto.php#L124 > > It is in public static function legacyDecrypt($ciphertext, $key) which is legacy(old and not recommended) way. > >> > >> You will also find zero projects using it for CSRF protection. > > > > > > You obviously does not understand HKDF RFC at all. (And don't read my > reply) > > It seems you consider HKDF as a specific KDF, but it is _not_. > > > > I'm telling you nobody uses it for CSRF and you can't disprove that, > but somehow that means I don't understand RFC 5869?! > > > HKDF is designed as general purpose KDF. It is clearly stated in RFC 5869 > > > > 4. Applications of HKDF > > > > HKDF is intended for use in a wide variety of KDF applications. > > > > > > Just because you cannot think of how general purpose KDF could be used > > for other purposes, it does not mean it should not be used other > purposes. > > Especially when it is designed for general purpose in the first place. > > > > First of all, KDF is a *cryptographic* term. > The fact that you don't know this should disqualify you of even being > involved in this discussion, and it is laughable that you're trying to > tell anybody that they don't understand RFC5869. > KDF is "Key Derivation Function". HKDF is designed as "General KDF" as RFC 5869 explicitly states in Section 4. > > Secondly, you're cherry-picking a single sentence, out of context and > twisting its meaning to serve your personal agenda. > Here's the entire paragraph in question: > > HKDF is intended for use in a wide variety of KDF applications. > These include the building of pseudorandom generators from imperfect > sources of randomness (such as a physical random number generator > (RNG)); the generation of pseudorandomness out of weak sources of > randomness, such as entropy collected from system events, user's > keystrokes, etc.; the derivation of cryptographic keys from a shared > Diffie-Hellman value in a key-agreement protocol; derivation of > symmetric keys from a hybrid public-key encryption scheme; key > derivation for key-wrapping mechanisms; and more. All of these > applications can benefit from the simplicity and multi-purpose nature > of HKDF, as well as from its analytical foundation. > > Link: https://tools.ietf.org/html/rfc5869#section-4 > Again, RFC 5869 explicitly states it is a "General KDF". There are specific examples, but there is _NO_ statement that defines HKDF for specific purpose. It even explains strange (but valid) KDF usage as CSPRNG. My CSRF token example is obviously a good KDF application example. What makes you think it is a bad one? > And finally, but what is most important as far as PHP documentation goes: > > - Can HKDF be somehow used for CSRF protection? Sure, a lot of things > *happen* to be usable for different things they weren't intended for. > "HKDF is intended for use in a wide variety of KDF applications." Nothing wrong for using wide variety of KDF tasks. > - Should HKDF be used for CSRF protection? Maybe, if you want an > overkill solution - a simple HMAC is more than sufficient if you want > to couple your CSRF tokens with the server state. > Overkill? Not at all. Should I list reasons why advanced CSRF token by HKDF is required/better? I repeat an explanation in my PHP RFC. NOTE: String concatenations have risk. If moderately secure hashing is acceptable, one could use hash() for URI specific CSRF token with expiration like $csrf_token = hash('sha3-256', $csrf_token_seed . $expire_timestamp . $the_uri); This is obviously worse way because of the "String concatenation". i.e. $csrf_token_seed . $expire_timestamp . $the_uri Better way is not to concatenate string. $csrf_token = hash_hmac('sha3-256', $csrf_token_seed, $expire_timestamp . $the_uri); This is still worse way because of the "String concatenation". i.e. $expire_timestamp . $the_uri // Where $expire_timestamp is low entropy salt. Again, better way is not to concatenate string. $csrf_token = bin2hex(hash_hkdf('sha3-256', $csrf_token_seed, 0, $the_uri, $expire_timestamp )); > - Is CSRF token generation what HKDF was made for? Absolutely NOT, > and you know it. > Absolutely valid because it is "Designed as general purpose KDF". Even though RFC 5869 explicitly states HKDF is not designed for "slow hashing" like PBKDF2(hash_pbkdf2) or crypt(hash_password), it could be used for password hashing _IF_ OKM and/or Salt could be stored in _secure_ system(s). i.e. OKM and/or Salt could be stored in other secure server(s). > It's none of our business to *invent* new use cases and document them > as if that's what everybody should do. > For all I care, use it however you wish in your own code, but the PHP > documentation is not your personal blog. > Did you read my reply to Nikita? CSRF token is a "Authentication Key" that validates request is _authentic_. Therefore, the CSRF example is one of a perfect HKDF application example even with your claim "HKDF is for cryptographic task". You insist HKDF is only for specific cryptographic tasks (I still don't know what you mean by this exactly. No valid examples yet.), how _authentication_ can be non cryptographic task? >> The vote ended with 1 Yes (you) and 14 No; not a single person has > >> agreed with you so far, and most have explicitly stated strong > >> disagreement with your proposed changes. Yet you insist on pushing > >> your *personal opinion*, ignoring everybody else and acting as if ~80 > >> mails haven't already been exchanged. > >> > >> > >> How is it even possible that you still believe that everybody is wrong > >> and you alone are right? Give it up already. > > > > > > Prove my idea in the manual (or my RFC) is wrong by logic, rather than > FUD. > > > > I just did, but since you insist - there's more. > You don't prove any. You only states "How RFC 5869 should be interpreted with your understanding". Previous hash(), hash_hmac() and hash_hkdf() example is a logical explanation why hash_hkdf()/HKDF is needed. i.e. String concatenations involve risks even with cryptographic hashes. Separating HMAC "Key" into "Salt" and "Info" makes HKDF useful to wide variety of applications. Optional "length" parameter adds more use cases which are rare. RFC 5869's HKDF is made for general purpose KDF obviously. Does RFC 5869 limit or specify the usage? ABSOLUTELY NOT. You seem misunderstood usage examples showed in RFC is the only HKDF applications. You seem misunderstood common mistake warnings, too. Your RFC lists multiple examples of using *user-provided plain-text > passwords* for IKM, and you describe those as valid use cases as follows: > > Well, I was prepared to compare HKDF to PBKDF2, as the latter also > uses HMACs and a salt, but I don't even have to do that. > Because guess what Section 4 of RFC 5869 says about passwords? The > very same "Applications of HKDF" section that you cherry-pick from: > > On the other hand, it is anticipated that some applications will not > be able to use HKDF "as-is" due to specific operational requirements, > or will be able to use it but without the full benefits of the > scheme. One significant example is the derivation of cryptographic > keys from a source of low entropy, such as a user's password. The > extract step in HKDF can concentrate existing entropy but cannot > amplify entropy. In the case of password-based KDFs, a main goal is > to slow down dictionary attacks using two ingredients: a salt value, > and the intentional slowing of the key derivation computation. HKDF > naturally accommodates the use of salt; however, a slowing down > mechanism is not part of this specification. Applications interested > in a password-based KDF should consider whether, for example, [PKCS5] > meets their needs better than HKDF. > > Link: https://tools.ietf.org/html/rfc5869#section-4 > > And this doesn't stop at passwords. Please note that this paragraph > explicitly states this: > > The extract step in HKDF can concentrate existing entropy but > cannot amplify entropy. > > Which means that it is NOT designed to do key stretching, or in other > words it should NOT be relied upon to produce strong outputs from weak > inputs - the exact scenario for which you wanted to make salts > non-optional. > I agree no KDF including HKDF will provide automatically secure keys by itself. This is the reason why the manual explicitly should state best practices and common mistakes. (And insisting "salt" as the first required parameter) The explanations are warnings for "HKDF as slow hashing" and "non secret salt". Applications, that _must_ store "Salt" and "Resulted Hash"(OKM) in the _same_ DB, must not use HKDF "as-is". OKM and/or Salt must be stored in _secure_ system(s) when HKDF(or HMAC) is used for user entered password. This is explained already in this mail. "Non secret salt" never increase entropy. (This is common KDF application mistake) With HKDF, PRK must have enough entropy which attacker cannot guess with reasonable computation time. i.e. HMAC(IKM, Salt) must be secure. Strong key derivations, that make strong encryption keys from poor keys like user entered password, are very _common_ tasks. Users must do whenever it is possible. e.g. $secure_aes256_key = hex2bin(hash_hmac('sha3-256', $poor_user_password, $strong_SECRET_salt)); OR with hash_hkdf() $secure_aes256_key = hash_hkdf('sha3-256', $poor_user_password, 0, '', $strong_SECRET_salt); Salt obviously must be _SECRET_ (and have enough entropy), otherwise simple brute force attack works. I'm not sure how many times I showed this logically obvious example. Random strong _SECRET_ salt does produce strong PRK regardless of IKM, therefore increase OKM entropy. Explanation is omitted because it is obvious. > Is this FUD? Do we all still not understand HKDF, while you're the > only person on the planet who does? > You are insisting false FUD that HKDF is for specific task(s) and valid KDF usages as invalid. In this mail, you are insisting HKDF cannot increase OKM entropy while random _secret_ salt can. No cryptographers will recommend "Omitting salt", but recommend it whenever it's possible. No cryptographers will consider HKDF based advanced CSRF token as invalid HKDF application. If any, please let me know. Anyway, salt as the last optional parameter is total nonsense, claim that KDF based CSRF as invalid HKDF application as well. And will you at least stop with the "I will commit unless somebody > comments" emails? > When everybody is unanimously against your changes, that means don't do > them. > Not everybody, I presume. I don't see logically correct objections yet. Regards, P.S. I've presented more than enough good HKDF usage examples that users should/must provide proper salt in my PHP RFC. You show _no_ examples that are valid/recommended/common HKDF usage only with length and length/info. Please give some examples that could be common and useful like advanced CSRF token by HKDF. I don't need your view of HKDF RFC or usage, but I do need good practical examples that justify your point of view. Please don't waste of your/my time, just give some good examples in next reply. Thanks. -- Yasuo Ohgaki yohgaki@ohgaki.net --94eb2c05bc82ff84b2054e565bc5--