Hi Andrey,

On Tue, Apr 25, 2017 at 7:17 PM, Andrey Andreev <n...@devilix.net> wrote:

> Hi,
>
> On Tue, Apr 25, 2017 at 3:28 AM, Yasuo Ohgaki <yohg...@ohgaki.net> 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
yohg...@ohgaki.net

Reply via email to