9
$\begingroup$

NIST recommends Krawczyk's HMAC-based key derivation function (HKDF) in SP-800-56C (PDF). HKDF shall e.g. be used to create keys from shared secrets after Diffie Hellman key establishment.

NIST states in the same doc:

Each call to the randomness extraction step requires a freshly computed shared secret $Z$, and this shared secret shall be zeroized immediately following its use in the extraction process.

Why is it not recommended to derive multiple keys from the same $Z$, e.g. why not derive a key for data encryption and a key for authentication from the same $Z$ using different info strings? If I still do it, what weaknesses might the derived keys be facing? Is it simply bad practice (without deep explanation) to do so since the derived keys obviously are related? Krawczyk seems to think that multiple derivations from the secret are expected use (see section 3.2 in RFC 5869, my interpretation).

Does salting the HKDF with a good random salt change my risks when deriving multiple keys from a single $Z$?

$\endgroup$
6
$\begingroup$

It depends on how you use HKDF to derive multiple keys.

Background: HKDF consists of two stages: first HKDF-Extract computes an intermediate value from the randomness source; then HKDF-Expand can be used to generate one or more session keys from the intermediate value.

The right way is to use HKDF-Extract once, and then call HKDF-Expand multiple times, with multiple different info strings. In other words, to derive two session keys, you'd call HKDF-Extract once and HKDF-Expand twice. If you do that, then this is a perfectly good practice -- it is exactly what HKDF was designed for.

The wrong way is to call the entire HKDF process twice, with two different salts. Some implementations of HKDF might not separate out the two stages, and just combine them; if you used that, and performed the entire process twice (using HKDF-Extract twice and HKDF-Expand twice), then this is not the intended way to use HKDF.

Everything is fine if you use the "right" way, so for the rest of this question I assume you were asking about the "wrong" way. There are two answers about whether this is a good idea: the "engineering" answer, and the "principled" answer.

The engineering answer is that, in practice, if you generate two keys using two different info strings, I suspect you'd probably get away with it without problems. If we model the hash as a random oracle (admittedly a very strong "assumption"), then I suspect it might be possible to demonstrate that what you propose is OK. Disclaimers: I haven't analyzed this, and I'm certainly not going to give you any guarantees -- if you do what you propose, cryptographers will wag their finger and say "tsk, tsk", and rightly so. I suspect you'd probably get away with it (it's not the worst sin you could make), but if something does go wrong, cryptographers aren't going to take the blame -- it's all on you.

The more principled answer is that if you do what you propose, you are misusing the HKDF primitive. The HKDF is only intended to be applied to a single $Z$ once. It is intended to turn an unguessable value into something that looks uniformly random. It has been analyzed for that use. It was not designed to derive multiple keys from the same $Z$: it hasn't been analyzed for that kind of use case, since that's not what it was designed for. So, you're throwing away the benefits you could get from the public analysis of HKDF if you use it in a way that it wasn't designed for.

Consequently, given that it is so easy to use HKDF the right way, you should probably do that.

$\endgroup$
  • 7
    $\begingroup$ As HKDF has a variable-length output, couldn't we just produce enough output for both keys and then split it in two, instead of using another PRF after HKDF? $\endgroup$ – Paŭlo Ebermann Nov 15 '12 at 23:14
  • $\begingroup$ @PaŭloEbermann, good point, yes, I think that would be OK too. $\endgroup$ – D.W. Nov 15 '12 at 23:52
  • $\begingroup$ this is what is done in TLS. They use HKDF on a shared secret to produce enough keys. $\endgroup$ – David 天宇 Wong Oct 18 '16 at 20:19
  • 2
    $\begingroup$ Isn't the point of the info parameter of the Expand phase so that you can derive multiple keys? $\endgroup$ – Cocowalla May 8 '18 at 21:12
4
$\begingroup$

What you propose—using the intermediate derivation key $K_{\mathit{DK}}$ from a single input $Z$ to derive many output keys with distinct info strings—is perfectly fine.

The excerpt you quoted is about the HKDF-Extract step, not the HKDF-Expand step. What it is saying is that you should not use the same $Z$ with many different salts for HKDF-Extract: use it with one salt, and then erase it. That excerpt says nothing about HKDF-Expand with different info strings, however.

RFC 5869 is clearer on the point (emphasis added):

HKDF follows the "extract-then-expand" paradigm, where the KDF logically consists of two modules. The first stage takes the input keying material and "extracts" from it a fixed-length pseudorandom key K. The second stage "expands" the key K into several additional pseudorandom keys (the output of the KDF).

The standard security reduction for HKDF applies to an adversary who can query HKDF-Expand for many info strings adaptively, with the theorem parametrized by the number of queries, so your proposed use falls squarely within the intended and studied use of HKDF. This applies whether or not you use a salt.

You could generate a single key out of HKDF-Extract and HKDF-Expand, and feed it into another PRF to derive more keys. But to do so would be silly when HKDF-Expand already does exactly that.

$\endgroup$
1
$\begingroup$

A key derivation function is intuitively "purifying" the entropy in the group element Z into uniformly random (looking) bits that can used as a key for other purposes. It is not designed to produce "multiple keys" from the same Z, and one should definitely not call the KDF on the same Z twice (even with different salts) and expect to get two independent keys.

If you want more key material beyond the output of one call to the KDF, the high level approach should be to apply the KDF to Z only once to get a single key, and then apply a pseudorandom generator (e.g., AES in counter mode) to that key to get multiple keys. This approach will be sound in the sense that it can proven secure in an appropriate model, assuming Z is pseudorandom, the KDF meets a natural notion of "purifying," and the pseudorandom generator is secure.

$\endgroup$
  • 1
    $\begingroup$ So HKDF (not being any old KDF but e.g. HMAC-SHA-256/512 based) is still not providing the step of applying a pseudorandom generator? $\endgroup$ – NotACryptographer Nov 13 '12 at 14:53
  • 1
    $\begingroup$ The output of K = HKDF(Z,r) will look like a random key when Z is a random group element and r is a random salt. But K1 = HKDF(Z,r) and K2 = HKDF(Z,r') will not look like two independent random keys, even when the salts r,r' are independent (at least this is the case with the concept of KDFs I am familiar with). However, if we take (K1,K2) = PRG(HKDF(Z,r)), then they will look random and independent. $\endgroup$ – David Cash Nov 13 '12 at 16:48
  • 1
    $\begingroup$ HKDF-Expand is itself a pseudorandom generator as you recommend to turn one key into many keys, except with an arbitrary-length info parameter for a structured identifier of purpose rather than a limited-size AES block counter. That's half the point of HKDF itself. While it's true that in general something called a ‘KDF’ might just serve the purpose of HKDF-Extract to turn a high-entropy secret into a short uniform random secret, HKDF as the original poster asked about already includes the PRG/PRF part builtin via HKDF-Expand. $\endgroup$ – Squeamish Ossifrage Sep 12 at 18:46
  • $\begingroup$ I agree with Squeamish here. This answer is completely skipping over the Info or OtherInfo or label (or even counter) that is commonly input to derive many independent bytes from a single shared secret Z. A KDF is a cryptographic algorithm that specializes in deriving keys; the idea that you should only derive one key using a KDF algorithm is categorically wrong. Preferably you derive multiple keys be applying multiple labels (or any other enumeration) to the same shared secret Z. $\endgroup$ – Maarten Bodewes Sep 12 at 21:48
-1
$\begingroup$

The HKDF RFC contains formulations such as:

The second stage "expands" the key K into several additional pseudorandom keys (the output of the KDF).

and:

The second stage "expands" the pseudorandom key to the desired length; the number and lengths of the output keys depend on the specific cryptographic algorithms for which the keys are needed.

Both quotes appear already in the introduction (emphases mine).

As you already point out, Section 3.2 describes the info value and states:

In particular, it may prevent the derivation of the same keying material for different contexts (when the same input key material (IKM) is used in such different contexts).

All these quotes taken together seem to rather strongly indicate that deriving several keys from the same IKM is a perfectly valid and even intended use case of HKDF.

However, there is also a rather strong caveat in the introduction:

In many applications, the input keying material is not necessarily distributed uniformly, and the attacker may have some partial knowledge about it (for example, a Diffie-Hellman value computed by a key exchange protocol) ...

The concrete case of DH key exchange is thus even explicitly mentioned as one case where an attacker has partial knowledge of the IKM.

It would thus seem prudent to base the derivation of further keys on a new shared secret in this particular case of IKM.

$\endgroup$
  • $\begingroup$ No, this would be the case where you would first use HKDF-extract before HKDF-Expand. There is no way that deriving multiple keys using HKDF would somehow be weaker than deriving just one key from it. $\endgroup$ – Maarten Bodewes Sep 12 at 21:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.