hash_hkdf() signature

php.internals

Yasuo Ohgaki

9 years ago
Hi Nikita, Andrey and all, My apologies, I misread mails by super sloppy reading. I'll explain basis by my idea clearly and properly this time. This mail is long. Basis of my idea is - Salt is made to optional only for applications that such value is not available. (From RFC 5869) - Omitting salt could lead to security disaster. i.e. password leak. - Combined key, output key and salt, as final key(combined key) is common in many use cases. - Many HKDF applications with PHP must/should have salt for better implementation. - API should encourage "salt" use by its signature. (From RFC 5869) Ref: https://tools.ietf.org/html/rfc5869 Before restart discussion, there should be rationale for others. In theory, cryptographic hashes are cryptographically secure. Therefore, following operations should be considered as secure by definition. $new_key = sha1('some original key' . 'strong salt' . 'some info'); $signature = sha1('some data' . 'strong key'); However, in real world, people come up with better idea for cryptographic hashes. Sometimes people invent efficient way to attack cryptographic hashes. HMAC is known and proven method to generate more secure signature. Therefore, $signature = hash_hmac('sha1', 'some data', 'some key'); is secure even when cryptographic hash had minor defect(s). HKDF is made to generate secure new keys from existing key suitable for required operations by using HMAC. HKDF inputs - IKM, input key which may be weak or strong - salt, some entropy which makes HKDF stronger overall, may be secret or non secret/weak or strong. - info, which specifies HKDF contexts that are non secret usually. e.g. a protocol number, algorithm identifiers, user identities, etc. - length(L), output key length HKDF calculates output key(OKM) as follows Extract step PRK = HMAC-Hash(salt, IKM) This step is designed to make strong output key(OKM) and PRK always. OKM to be secure, either IKM or salt must be strong. Expand step N = ceil(L/HashLen) T = T(1) | T(2) | T(3) | ... | T(N) OKM = first L octets of T where: T(0) = empty string (zero length) T(1) = HMAC-Hash(PRK, T(0) | info | 0x01) T(2) = HMAC-Hash(PRK, T(1) | info | 0x02) T(3) = HMAC-Hash(PRK, T(2) | info | 0x03) Note: OKM is output key material that is return value from HKDF. This step is designed to make derived key have the length(L) from strong key(PRK) generated by Extract step. Key context(info) is distinguished by this step also. Both salt and info is optional, but RFC 5869 states differently. "HKDF is defined to operate with and without random salt. This is done to accommodate applications where a salt value is not available. We stress, however, that the use of salt adds significantly to the strength of HKDF, ensuring independence between different uses of the hash function, supporting "source-independent" extraction, and strengthening the analytical results that back the HKDF design." This statement implies salt is almost mandatory parameter for HKDF when salt can be used. In contrast, info is described as pure optional parameter for key context. "While the 'info' value is optional in the definition of HKDF, it is often of great importance in applications. Its main objective is to bind the derived key material to application- and context-specific information. For example, 'info' may contain a protocol number, algorithm identifiers, user identities, etc." With regard to mandatoriness parameters, strong salt is mandatory to derive cryptographically strong key when input key is weak, while info/length is optional always. In addition, it is common that salt being used as a part of combined keys. Salt is mandatory for such applications. There are many authentication implementations that use - key which does not disclose original key by hashing - nonce(salt) Access permission with timeout is another typical usage that requires timestamp as salt and combined key. HKDF can produce secure key, which protects input key(IKM) and generates strong output key (OKM), but this is true only when IKM or salt is strong. Use of weak IKM and salt could lead password leak. For above reasons, I'm proposing change string hash_hkdf(string $hash, string $ikm [, int $length=0 [, string $info='' [, string $salt='']]]) to string hash_hkdf(string $hash, string $ikm, string $salt [, string $info='' [, int $length=0 ]]) - To omit salt, $salt=NULL. $salt='' raise exception. On Mon, Jan 16, 2017 at 8:08 PM, Nikita Popov <nikita.ppv@gmail.com> wrote:
> Making the salt required makes no sense to me. > > HKDF has a number of different applications: > a) Derive multiple strong keys from strong keying material. Typical case > for this is deriving independent encryption and authentication keys from a > master key. This requires only specification of $length. A salt is neither > necessary nor useful in this case, because you start with strong > cryptographic keying material. >
Very true. Shorter password would hide IKM/salt/info state, so shorter output key could be said more secure. e.g. SHA512 and 32 bytes output key This is only applicable when IKM and/or salt is strong, though. If we could assume IKM to be always cryptographic Extract step PRK = HMAC-Hash(salt, IKM) is not needed, but only T(1) = HMAC-Hash(PRK, T(0) | info | 0x01) In short, if key is strong, hash_hmac('sha256', $key, 1) substr(hash_hmac('sha256', $key, 1), 0, $length) is good enough. Thus, HKDF is not needed. But in real world, IKM does not have to be cryptographically secure. Therefore, HKDF users must ensure secure PRK by PRK = HMAC-Hash(salt, IKM) This requirement makes "salt" more important than "length" because strong PRK is mandatory for HKDF security. i.e. IKM or salt must be strong always. For the same reason as "Apply HTML escape for all vars", random salt regardless of key strength whenever possible, is safer. It prevents weak IKM leak by misuse effectively. b) Generating per-session (or similar) keys from a (strong cryptographic)
> master key. For this purpose you can specify the $info parameter. again, a > salt is neither necessary nor useful in this case. (You could probably also > use $salt instead of $info in this case, but the design of the function > implies that $info should be used for this purpose.) >
Assuming $_SESSION['master_key'] = random_bytes(80); // Keep this for this session. and current hash_hkdf() function signature string hash_hkdf(string $hash_function, string $ikm, [int $length [, string $info [, string $salt]]]); Your idea might be $new_key = hash_hkdf('sha256', $_SESSION['master_key'], 0, session_id()); Although it works. Session ID is not identity, but key that identifies user's connection. Key(entropy) value for info parameter violates the RFC recommended info usage. OR You might be assuming logged in session, then username can be used as info parameter. $new_key = hash_hkdf('sha256', $_SESSION['master_key'], 0, $_SESSION['username']); username is non secret user identifier. This usage matches RFC recommended usage. However, username is only available for logged in session, when username is changed during session it stops working. It stops working at logout also. And most important of all, this is not a per-session, but per-user... The RFC compliant implementation with PHP is to use session_id() as secret salt. $new_key = hash_hkdf('sha256', $_SESSION['master_key'], 0, '', session_id()); This method is better because it works regardless of authentication/changed username. However, this version still has problem with regenerated session ID. This could be fixed with better salt. $_SESSION['salt'] = session_create_id(); then $new_key = hash_hkdf('sha256', $_SESSION['master_key'], 0, '', $_SESSION['salt']); This works for any session always. Both $new_key and $_SESSION['salt'] could be safely passed as page content unlike session_id() as salt. I have other examples like these that illustrates, users should consider salt usage. c) Extracting strong cryptographic keying material from weak cryptographic
> keying material. Standard example here is extracting strong keys from DH > g^xy values (which are non-uniform) and similar. This is the usage that > benefits from a $salt. >
Even when strong IKM is used, low entropy salt like timestamp can be used as combined key. This use case would be one of the most used with PHP. Remember that HKDF is an extract-and-expand algorithm, and the extract step
> (which uses the salt) is only necessary if the input keying material is > weak. We always include the extract step for compatibility with the overall > HKDF construction (per the RFCs recommendation), but it's essentially just > an unnecessary operation if you work on strong keying material. >
I presume reply to a) should be sufficient for this. Strong(cryptographic) key, e.g. random_bytes(80), can be used in many cases. Even when key supposed to be strong key, it would be better to use salt to derive even stronger key. This practice will prevent users to omit salt for weak input keys accidentally. Slat could be used as combined key also. The only thing that we may want to discuss is whether we should swap the
> $info and the $salt parameters. This depends on which usage (b or c) we > consider more likely.
"length" has little relevance with respect to IKM protection and output key (OKM) security. While it is user's responsibility to ensure secure PRK and protect IKM by Extract step PRK = HMAC-Hash(salt, IKM) HKDF info parameter is unrelated to IKM protection and output key as per the RFC, but salt has the responsibility. Therefore, "salt" must have priority over "info" and "length", IMHO. Importance with regard to security: salt >>>> info > length We also must consider how output key and salt is used in real world PHP applications. There are applications that use output key and salt as combined key. e.g. authentication, access key with expiration // URL access key with expiration $expire = time() + 90; // 90 sec timeout. Low entropy salt is allowed with strong IKM. $key = hash_hkdf('sha256', $_SESSION['strong_master_key'], 0, $URL, $expire); // Send $key and $expire as combined key for $URL hash_hkdf() is key generation function and output key and salt are used as "combined key" in many use cases. Parameter being as key is important. Therefore, commonly used combined key(salt) is better to locate after IKM. Importance with regard to common use case: salt >> info > length Although there are HKDF usage without salt, many HKDF applications with PHP require or are better with salt. e.g. Previous per-session encryption. Developers will develop better application if they consider how salt could be used. Therefore, salt is better to be required parameter and omit it only when salt cannot be used. Importance with regard to education: salt >>> info > length (User must learn safe salt usage) "length" is the least for me. "salt" and "info" has important effect for derived key/input key security. These 2 should have priority over "length". Making the most responsible/sensitive parameter(salt) which is currently optional to required parameter should not be a issue for users. If it is C, I don't care and accept whatever signature. C is full of pit holes already. I just don't want to see news, "Passwords are stolen from PHP app!". hash_hkdf() is could be misused easily like hash_hkdf('sha256', $weak_ikm, 9); // We can generate strong key easily, Nice! hash_hkdf('sha256', $weak_ikm, 9, 'Super User Only'); // Safe key for super user hash_hkdf('sha256', $strong_ikm, 4); // Secure and nice password for super secret These are security disaster. If salt is required, users would always think about it at least. Length should not be shortened unless user is absolutely sure. If there are unclear sentences, please let me know. Thank you for reading long mail! Regards, P.S. I'll be more careful, but I become very sloppy mail reader sometimes. I appreciate if you could let know via private email. Thank you!
-- Yasuo Ohgaki yohgaki@ohgaki.net

Scott Arciszewski

9 years ago
On Tue, Feb 7, 2017 at 2:35 PM, Yasuo Ohgaki <yohgaki@ohgaki.net> wrote:
> Hi Nikita, Andrey and all,
​<snip>​
>
Regards,
> > P.S. I'll be more careful, but I become very sloppy mail reader sometimes. > I appreciate if you could let know via private email. Thank you! > > -- > Yasuo Ohgaki > yohgaki@ohgaki.net >
​Hi,​ Although there are HKDF usage without salt, many HKDF applications with PHP
> require or are better with salt. e.g. Previous per-session encryption. > Developers > will develop better application if they consider how salt could be used. > Therefore, > salt is better to be required parameter and omit it only when salt cannot
be used.​
> >
​---​ One such real-world use case: Defuse v1 used HKDF without a salt. https://github.com/defuse/php-encryption/blob/b87737b2eec06b13f025cabea847338fa203d1b4/Crypto.php#L157-L170 https://github.com/defuse/php-encryption/blob/b87737b2eec06b13f025cabea847338fa203d1b4/Crypto.php#L358 In version 2, we included a 32-byte random salt for each encryption, which was stored next to the AES-256-CTR nonce in the ciphertext. (Both the nonce and HKDF-salt, as well as the version information header, are covered by the HMAC of the ciphertext.) The end result: Instead of having to worry about birthday collisions after you've seen 2^64 AES outputs (because 128-bit randomly generated nonce), now you need 2^192 before you have a useful collision. Although the RFC itself says that salts are optional, the argument to make them required in PHP's implementation has merit. The only downside is: If you're integrating with an implementation that doesn't require salts, and the application doesn't use salts, you're out of luck. Is that enough of a downside to dismiss an argument for better security? Maybe. Scott Arciszewski Chief Development Officer Paragon Initiative Enterprises <https://paragonie.com/>​

Yasuo Ohgaki

9 years ago
Hi Scott, On Wed, Feb 8, 2017 at 5:22 AM, Scott Arciszewski <scott@paragonie.com> wrote:
> > One such real-world use case: Defuse v1 used HKDF without a salt. > > https://github.com/defuse/php-encryption/blob/ > b87737b2eec06b13f025cabea847338fa203d1b4/Crypto.php#L157-L170 > https://github.com/defuse/php-encryption/blob/ > b87737b2eec06b13f025cabea847338fa203d1b4/Crypto.php#L358 > > In version 2, we included a 32-byte random salt for each encryption, which > was stored next to the AES-256-CTR nonce in the ciphertext. (Both the nonce > and HKDF-salt, as well as the version information header, are covered by > the HMAC of the ciphertext.) > > The end result: Instead of having to worry about birthday collisions after > you've seen 2^64 AES outputs (because 128-bit randomly generated nonce), > now you need 2^192 before you have a useful collision. > > Although the RFC itself says that salts are optional, the argument to make > them required in PHP's implementation has merit. The only downside is: If > you're integrating with an implementation that doesn't require salts, and > the application doesn't use salts, you're out of luck. Is that enough of a > downside to dismiss an argument for better security? Maybe. >
There are applications that do not require salt. In this case, all users has to do is $salt = NULL to omit $salt. Current signature has $length as the first optional parameter which would be set to "0" in many cases if not most. i.e. Just deriving new key from strong $ikm would not be typical. Requiring "$salt = NULL" to omit salt would not hurt API use much compare to current signature that requires "$length = 0" for most cases, I suppose. Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net

Yasuo Ohgaki

9 years ago
Forgot to mention the most important. On Wed, Feb 8, 2017 at 6:16 PM, Yasuo Ohgaki <yohgaki@ohgaki.net> wrote:
> Is that enough of a downside to dismiss an argument for better security? > Maybe
I suppose so. It is very clear that "salt" is the most important for derived key security, "info" is next, then "length". Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net

Andrey Andreev

9 years ago
Hi, On Tue, Feb 7, 2017 at 10:22 PM, Scott Arciszewski <scott@paragonie.com> wrote:
> > > Although the RFC itself says that salts are optional, the argument to make > them required in PHP's implementation has merit. The only downside is: If > you're integrating with an implementation that doesn't require salts, and > the application doesn't use salts, you're out of luck. Is that enough of a > downside to dismiss an argument for better security? Maybe. > >
I said this in another thread already, but I'll re-iterate here ... Using a salt should be recommended, but the suggestion here takes that out of context and misses a key point - that the Length and Info params are not of any less importance overall. - Length is effectively the key size and is in fact not optional in RFC5869*. You have to really know what you're doing if you don't use it, and choose the hash function very carefully. I'd argue that if you know this well enough, you'd also know what to do with Salt. - Info is technically optional, but pretty much the feature why you'd choose HKDF over other KDFs. It's what makes HKDF's more useful in that it enables derivation of multiple OKMs from a single IKM. If you don't need Info, chances are you don't need HKDF. One could use Salt for the purposes of Info, but that would be misusing the algorithm. Over-focusing on Section 3.1 of the specification, while at the same time ignoring Section 3.2 - arbitrarily making OptionalParamX mandatory because the note about it mentions the word "security". Noble, but misguided. I'd have no problem if ALL of the params were made non-optional - I'm all for that, but either do that or leave it untouched. * RFC 5869: https://tools.ietf.org/html/rfc5869 Cheers, Andrey.

Scott Arciszewski

9 years ago
On Wed, Feb 8, 2017 at 4:16 AM, Yasuo Ohgaki <yohgaki@ohgaki.net> wrote:
> Hi Scott, > > There are applications that do not require salt. In this case, all users > has to do is > $salt = NULL > to omit $salt. >
Great. On Wed, Feb 8, 2017 at 6:27 AM, Andrey Andreev <narf@devilix.net> wrote:
> Hi, > > On Tue, Feb 7, 2017 at 10:22 PM, Scott Arciszewski <scott@paragonie.com> > wrote: > >> >> >> Although the RFC itself says that salts are optional, the argument to >> make them required in PHP's implementation has merit. The only downside is: >> If you're integrating with an implementation that doesn't require salts, >> and the application doesn't use salts, you're out of luck. Is that enough >> of a downside to dismiss an argument for better security? Maybe. >> >> > I said this in another thread already, but I'll re-iterate here ... Using > a salt should be recommended, but the suggestion here takes that out of > context and misses a key point - that the Length and Info params are not of > any less importance overall. > > - Length is effectively the key size and is in fact not optional in > RFC5869*. You have to really know what you're doing if you don't use it, > and choose the hash function very carefully. I'd argue that if you know > this well enough, you'd also know what to do with Salt. > - Info is technically optional, but pretty much the feature why you'd > choose HKDF over other KDFs. It's what makes HKDF's more useful in that it > enables derivation of multiple OKMs from a single IKM. If you don't need > Info, chances are you don't need HKDF. > > One could use Salt for the purposes of Info, but that would be misusing > the algorithm. > Over-focusing on Section 3.1 of the specification, while at the same time > ignoring Section 3.2 - arbitrarily making OptionalParamX mandatory because > the note about it mentions the word "security". Noble, but misguided. > > I'd have no problem if ALL of the params were made non-optional - I'm all > for that, but either do that or leave it untouched. > > * RFC 5869: https://tools.ietf.org/html/rfc5869 > > Cheers, > Andrey. >
Given everything discussed in this sub-thread so far, ​I would be in favor of making everything non-optional. Scott Arciszewski Chief Development Officer Paragon Initiative Enterprises <https://paragonie.com/>​

Yasuo Ohgaki

9 years ago
Hi all and Scott, On Wed, Feb 8, 2017 at 11:22 PM, Scott Arciszewski <scott@paragonie.com> wrote:
> On Wed, Feb 8, 2017 at 6:27 AM, Andrey Andreev <narf@devilix.net> wrote: > >> Hi, >> >> On Tue, Feb 7, 2017 at 10:22 PM, Scott Arciszewski <scott@paragonie.com> >> wrote: >> >>> >>> >>> Although the RFC itself says that salts are optional, the argument to >>> make them required in PHP's implementation has merit. The only downside is: >>> If you're integrating with an implementation that doesn't require salts, >>> and the application doesn't use salts, you're out of luck. Is that enough >>> of a downside to dismiss an argument for better security? Maybe. >>> >>> >> I said this in another thread already, but I'll re-iterate here ... Using >> a salt should be recommended, but the suggestion here takes that out of >> context and misses a key point - that the Length and Info params are not of >> any less importance overall. >> >> - Length is effectively the key size and is in fact not optional in >> RFC5869*. You have to really know what you're doing if you don't use it, >> and choose the hash function very carefully. I'd argue that if you know >> this well enough, you'd also know what to do with Salt. >> - Info is technically optional, but pretty much the feature why you'd >> choose HKDF over other KDFs. It's what makes HKDF's more useful in that it >> enables derivation of multiple OKMs from a single IKM. If you don't need >> Info, chances are you don't need HKDF. >> >> One could use Salt for the purposes of Info, but that would be misusing >> the algorithm. >> Over-focusing on Section 3.1 of the specification, while at the same time >> ignoring Section 3.2 - arbitrarily making OptionalParamX mandatory because >> the note about it mentions the word "security". Noble, but misguided. >> >> I'd have no problem if ALL of the params were made non-optional - I'm all >> for that, but either do that or leave it untouched. >> >> * RFC 5869: https://tools.ietf.org/html/rfc5869 >> >> Cheers, >> Andrey. >> > > > Given everything discussed in this sub-thread so far, ​I would be in favor > of making everything non-optional. >
I'm OK with making 'salt' and 'info' required. Users should consider 'info'(key context) could be used almost always before omitting it. I suppose most developers will use 'length' for shorter length. i.e. Weaker output keys. If it's not too short, shorter key length works. I'm not sure if shorter output key length, that would weaken the key, does any good in general . Note: longer output key does not make output key stronger. It may hide used hash function, though. Most use cases would be AWS S3 pre-signed URL like usage that users do not have to care long keys. With such use cases, users are better to use key as is. i.e. Use default hash output length. There may be vote option for length, but I'm in favor of leave it as optional. I do care about parameter order, but what to be required is not too much concern to me. Regards, BTW, I don't think of typical PHP application that requires human typable short password with HKDF. What kind of application would be? Thank you.
-- Yasuo Ohgaki yohgaki@ohgaki.net

Andrey Andreev

9 years ago
Hi Yasuo, The fact that you continue to talk about passwords and other low-entropy data as IKM shows, yet again, that you don't understand HKDF. It is simply not a password-based KDF; if you want that - use PBKDF2. Please read Section 4* of the spec: https://tools.ietf.org/html/rfc5869.html#section-4 In fact, at one point I suggested the function be named just 'hkdf()' as a way of discouraging such misuse, because a lot of people associate the word "hash" with password handling. And this ...
> I suppose most developers will use 'length' for shorter length. > i.e. Weaker output keys. If it's not too short, shorter key length works. > >
Shows that you shouldn't be trusted with anything related to cryptography either. I may be no cryptographer myself, but one thing I know for sure is that shorter than required key lengths are *never* ok, and most encryption algorithms have a *fixed* key length. Also, this is the last time I reply to you on this topic. You're just impossible to reason with. Cheers, Andrey.

Yasuo Ohgaki

9 years ago
Hi Andrey, How the manual page would be. Would it be "Even though 'slat' is the last optional parameter that users may omit easily by mistake, users _must_ set strong salt for weak $ikm. This is mandatory requirement for HKDF to work. In addition, it is advices to set salt whenever possible as RFC 5689 recommends" It can't make sense for new function. On Thu, Feb 9, 2017 at 7:59 PM, Andrey Andreev <narf@devilix.net> wrote:
> > The fact that you continue to talk about passwords and other low-entropy > data as IKM shows, yet again, that you don't understand HKDF. > It is simply not a password-based KDF; if you want that - use PBKDF2. > Please read Section 4* of the spec: https://tools.ietf.org/html/ > rfc5869.html#section-4 >
PHP would not be a language that builds low level crypto library/feature. I'm not sure what you mean by this. What sentences you refer as I don't understand? I assumed you would like to derive human typable password because you prefer to have the most priority for "length". Do you have any typical "length" use with PHP? HKDF relies on PRK being cryptographically strong. Extract step PRK = HMAC-Hash(salt, IKM) You should understand users _must_ make sure either "salt" or "IKM" is strong for HKDF to work. Since hash_hkdf() is generic function, you never can make sure IKM to be strong always. With this fact alone, salt must have the most priority.
> In fact, at one point I suggested the function be named just 'hkdf()' as a > way of discouraging such misuse, because a lot of people associate the word > "hash" with password handling. >
> And this ... > > >> I suppose most developers will use 'length' for shorter length. >> i.e. Weaker output keys. If it's not too short, shorter key length works. >> >> > Shows that you shouldn't be trusted with anything related to cryptography > either. > I may be no cryptographer myself, but one thing I know for sure is that > shorter than required key lengths are *never* ok, and most encryption > algorithms have a *fixed* key length. >
Are you assuming converting crypto keys to be other length would be the typical HKDF usage with PHP? Then, I have to say your assumption is wrong. It would be most used for CSRF key generation, object access control, e.g. AWS S3 presigned URL, or anything related to web app, not low level crypto. Discussion so far would not justify use of vulnerable, i.e. PRK could be weak very easily, signature. And you don't answer questions to you: ---------------- Why you recommends following usage? hash_hkdf('sha256', $weak_ikm, 9); // We can generate strong key easily, Nice! <= Must not do this. ---------------- ---------------- What's the reason why you trying to disregard RFC 5869 strongly recommends? ---------------- ---------------- Parameter order must reflect - importance of the parameter - likelihood to be used Salt is the most important for both input and output key security. Salt is mandatory and/or can be used for almost always with PHP. Salt usage results in better design/security. Salt is often used as final key as combined key. Does 'length' and/or 'info' achieve or designed for aboves? I don't think so. ---------------- ---------------- BTW, I don't think of typical PHP application that requires human typable short password with HKDF. What kind of application would be? ---------------- Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net

Scott Arciszewski

9 years ago
On Thu, Feb 9, 2017 at 7:51 AM, Yasuo Ohgaki <yohgaki@ohgaki.net> wrote:
> Hi Andrey, > > How the manual page would be. Would it be > > "Even though 'slat' is the last optional parameter that users may omit > easily > by mistake, users _must_ set strong salt for weak $ikm. This is > mandatory > requirement for HKDF to work. In addition, it is advices to set salt > whenever > possible as RFC 5689 recommends" > > It can't make sense for new function. > > On Thu, Feb 9, 2017 at 7:59 PM, Andrey Andreev <narf@devilix.net> wrote: > >> >> The fact that you continue to talk about passwords and other low-entropy >> data as IKM shows, yet again, that you don't understand HKDF. >> It is simply not a password-based KDF; if you want that - use PBKDF2. >> Please read Section 4* of the spec: https://tools.ietf.org/html/rf >> c5869.html#section-4 >> > > PHP would not be a language that builds low level crypto library/feature. > I'm not sure what you mean by this. What sentences you refer as I don't > understand? > > I assumed you would like to derive human typable password because > you prefer to have the most priority for "length". Do you have any typical > "length" use with PHP? > > HKDF relies on PRK being cryptographically strong. > > Extract step > PRK = HMAC-Hash(salt, IKM) > > You should understand users _must_ make sure either "salt" or "IKM" is > strong for HKDF to work. Since hash_hkdf() is generic function, you never > can make sure IKM to be strong always. > > With this fact alone, salt must have the most priority. > > >> In fact, at one point I suggested the function be named just 'hkdf()' as >> a way of discouraging such misuse, because a lot of people associate the >> word "hash" with password handling. >> > >> And this ... >> >> >>> I suppose most developers will use 'length' for shorter length. >>> i.e. Weaker output keys. If it's not too short, shorter key length >>> works. >>> >>> >> Shows that you shouldn't be trusted with anything related to cryptography >> either. >> I may be no cryptographer myself, but one thing I know for sure is that >> shorter than required key lengths are *never* ok, and most encryption >> algorithms have a *fixed* key length. >> > > Are you assuming converting crypto keys to be other length would be > the typical HKDF usage with PHP? > Then, I have to say your assumption is wrong. > > It would be most used for CSRF key generation, object access > control, e.g. AWS S3 presigned URL, or anything related to web > app, not low level crypto. > > Discussion so far would not justify use of vulnerable, i.e. PRK could > be weak very easily, signature. > > And you don't answer questions to you: > > ---------------- > Why you recommends following usage? > hash_hkdf('sha256', $weak_ikm, 9); // We can generate strong key easily, > Nice! <= Must not do this. > ---------------- > > ---------------- > What's the reason why you trying to disregard RFC 5869 strongly recommends? > ---------------- > > ---------------- > Parameter order must reflect > - importance of the parameter > - likelihood to be used > > Salt is the most important for both input and output key security. > Salt is mandatory and/or can be used for almost always with PHP. > Salt usage results in better design/security. > Salt is often used as final key as combined key. > > Does 'length' and/or 'info' achieve or designed for aboves? I don't think > so. > ---------------- > > ---------------- > BTW, I don't think of typical PHP application that requires > human typable short password with HKDF. What kind of > application would be? > ---------------- > > > > Regards, > > -- > Yasuo Ohgaki > yohgaki@ohgaki.net >
​Hi, ​
> ​HKDF relies on PRK being cryptographically strong. > ​ > ​
​Yes, b​ut not for the reasons you might suspect. ​The main use case of HKDF is to completely prevent related-key attacks, while splitting a single key into several for domain-specific purposes.​ Figuring out a subkey (by sheer luck) should also not give an attacker enough information to recreate the IKM. HKDF isn't meant for key stretching (e.g. use an 80-bit secret in an application that requires a 256-bit secret). That's what a password hashing function is for. (Bcrypt, Argon2, etc.) ​
> ​You should understand users _must_ make sure either "salt" or "IKM" is
strong for HKDF to work. Since hash_hkdf() is generic function, you never can make sure IKM to be strong always.​ ​​ Not quite. IKM has to be strong. The salt? Not so much. In cryptography protocols, salts are considered public information (even if you don't go out of your way to publish it). If you have a weak IKM but a strong salt (32 bytes from random_bytes()), you should still consider the OKM weak. ​
> Salt is the most important for both input and output key security. > Salt is mandatory and/or can be used for almost always with PHP. > Salt usage results in better design/security. > Salt is often used as final key as combined key.
Don't get me wrong: Having secure random salts is useful (serves as a useful way to enlarge the effective nonce in a symmetric encryption protocol). But the cryptographic secret in this protocol is IKM. Not the salt. Scott Arciszewski Chief Development Officer Paragon Initiative Enterprises <https://paragonie.com/>​

Yasuo Ohgaki

9 years ago
Hi Scott and all, On Thu, Feb 9, 2017 at 10:52 PM, Scott Arciszewski <scott@paragonie.com> wrote:
> > ​ >> ​HKDF relies on PRK being cryptographically strong. >> ​ >> ​ > > > > ​Yes, b​ut not for the reasons you might suspect. > > ​The main use case of HKDF is to completely prevent related-key attacks, > while splitting a single key into several for domain-specific purposes.​ > Figuring out a subkey (by sheer luck) should also not give an attacker > enough information to recreate the IKM. > > HKDF isn't meant for key stretching (e.g. use an 80-bit secret in an > application that requires a 256-bit secret). That's what a password hashing > function is for. (Bcrypt, Argon2, etc.) > > ​ >> ​You should understand users _must_ make sure either "salt" or "IKM" is > > strong for HKDF to work. Since hash_hkdf() is generic function, you never > > can make sure IKM to be strong always.​ > > ​​ > > Not quite. IKM has to be strong. The salt? Not so much. > > In cryptography protocols, salts are considered public information (even > if you don't go out of your way to publish it). > > If you have a weak IKM but a strong salt (32 bytes from random_bytes()), > you should still consider the OKM weak. > ​ > >> Salt is the most important for both input and output key security. >> Salt is mandatory and/or can be used for almost always with PHP. >> Salt usage results in better design/security. >> Salt is often used as final key as combined key. > > > > Don't get me wrong: Having secure random salts is useful (serves as a > useful way to enlarge the effective nonce in a symmetric encryption > protocol). > > But the cryptographic secret in this protocol is IKM. Not the salt. >
I agree that your description matches many typical crypto encryptions/authentication/etc. As you would know, there are some exceptions that encryption key is not really a random (Not cryptographically strong) If user could use strong IKM, they should use it, then salt could be for additional security. (HKDF IKM could be weak, salt could be secret, but you mentioned typical use case and best practice in crypto) The most typical HKDF application with PHP is access token key derivations with timestamp such as CSRF and Object Access token. For these applications, salt usage is strongly recommended, info(context) is recommended, length is OK with hash default. e.g. Generating CSRF token keys $expire = time()+900; // Even, non secret, low entropy salt makes HKDF OKM significantly stronger. $csrf_token = bin2hex(hash_hkdf('sha256', $_SESSION['CSRF_TOKEN_SEED'], 0, '', $expire)); then, send $expire and $csrf_token as access key. This could be done with hash_hmac() already. $csrf_token = hash_hmac('sha256', $_SESSION['CSRF_TOKEN_SEED'], $expire)); What's really good about HKDF is it can add additional non secret optional context(domain) safely, as you mentioned. // Make CSRF token only valid to 'Admin' features. $csrf_token = bin2hex(hash_hkdf('sha256', $_SESSION['CSRF_TOKEN_SEED'], 0, 'Admin', $expire)); // Should be OK, but this is risky compare to above. $csrf_token = hash_hmac('sha256', $_SESSION['CSRF_TOKEN_SEED'], $expire. '-Admin')); Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net

Yasuo Ohgaki

9 years ago
Hi Andrey, On Thu, Feb 9, 2017 at 7:59 PM, Andrey Andreev <narf@devilix.net> wrote:
> >> I suppose most developers will use 'length' for shorter length. >> i.e. Weaker output keys. If it's not too short, shorter key length works. >> >> > Shows that you shouldn't be trusted with anything related to cryptography > either. > I may be no cryptographer myself, but one thing I know for sure is that > shorter than required key lengths are *never* ok, and most encryption > algorithms have a *fixed* key length. > > Also, this is the last time I reply to you on this topic. You're just > impossible to reason with. >
I think I finally understand what you don't understand. Please read "Current Status" section of the draft PHP RFC. https://wiki.php.net/rfc/improve_hash_hkdf_parameter#current_status hash_hkdf() is simple hash_hmac() extension, why should not hash_hkdf() have compatible signature with hash_hmac()? Aside from it, $salt is "key" in many cases. There is no reason "key" to be the last optional parameter. Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net

Yasuo Ohgaki

9 years ago
Hi Andrey, On Wed, Feb 8, 2017 at 8:27 PM, Andrey Andreev <narf@devilix.net> wrote:
> On Tue, Feb 7, 2017 at 10:22 PM, Scott Arciszewski <scott@paragonie.com> > wrote: > >> >> >> Although the RFC itself says that salts are optional, the argument to >> make them required in PHP's implementation has merit. The only downside is: >> If you're integrating with an implementation that doesn't require salts, >> and the application doesn't use salts, you're out of luck. Is that enough >> of a downside to dismiss an argument for better security? Maybe. >> >> > I said this in another thread already, but I'll re-iterate here ... Using > a salt should be recommended, but the suggestion here takes that out of > context and misses a key point - that the Length and Info params are not of > any less importance overall. >
From the HKDF algorithm, importance is clear. Salt >>> info > length. Salt is the most important to secure input key. You seem to think following is the most important. - Salt could be optional _only_ when input key is cryptographically strong. What this means is - Salt is absolute _mandatory_ parameter unless input key is absolutely strong key. - Length is effectively the key size and is in fact not optional in
> RFC5869*. You have to really know what you're doing if you don't use it, > and choose the hash function very carefully. I'd argue that if you know > this well enough, >
- Info is technically optional, but pretty much the feature why you'd
> choose HKDF over other KDFs. It's what makes HKDF's more useful in that it > enables derivation of multiple OKMs from a single IKM. If you don't need > Info, chances are you don't need HKDF. >
There is huge difference between "Required to be implemented" and "Required/important as parameter". Implementation requirement is _nothing_ to do with parameter requirement/importance. 'salt' could be omitted the application that input key is always strong. This cannot be applied to generic API like hash_hkdf() that would be used by countless applications. Why you recommends following usage? hash_hkdf('sha256', $weak_ikm, 9); // We can generate strong key easily, Nice! <= Must not do this. One could use Salt for the purposes of Info, but that would be misusing the
> algorithm. >
I totally agree. HKDF is specific about 'salt' and 'info' task. Salt is entropy to make input/output key strong/stronger. Info is for output key context. Over-focusing on Section 3.1 of the specification, while at the same time
> ignoring Section 3.2 - arbitrarily making OptionalParamX mandatory because > the note about it mentions the word "security". Noble, but misguided. >
What's the reason why you trying to disregard RFC 5869 strongly recommends? "designers of applications are therefore encouraged to provide salt values to HKDF if such values can be obtained by the application." It seems you're mixed up with "Implementation requirement" and "Parameter requirement/importance". After all, we are implementing RFC 5869, why we should not follow recommendation?
> I'd have no problem if ALL of the params were made non-optional - I'm all > for that, but either do that or leave it untouched. > > * RFC 5869: https://tools.ietf.org/html/rfc5869 >
While I don't mind requiring both 'salt' and 'info', I strongly disagree with the current parameter order and 'length' is pure optional parameter. 'info' is important but optional. 'salt' can only be optional when input key is absolutely cryptographically strong. Parameter order must reflect - importance of the parameter - likelihood to be used Salt is the most important for both input and output key security. Salt is mandatory and/or can be used for almost always with PHP. Salt usage results in better design/security. Salt is often used as final key as combined key. Does 'length' and/or 'info' achieve or designed for aboves? I don't think so. hash_hkdf() is generic API. $ikm cannot be strong key always. Assuming $ikm to be strong is simply wrong assumption. Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net