6

I'm working on a project where I need to derive several child keys from a parent key. I'm not a cryptography expert, so I'd really appreciate a simple explanation to help me understand the best practices and potential risks involved.

Here's the method I'm currently considering; I derive each child key using the SHA-256 hash function as follows:

child_key = SHA256( SHA256( 256_bit_parent_key || label ) || version )

Where:

  • parent_key is the original key from which I'm deriving child keys.
  • label is a unique UTF-8 string identifier for each child.
  • version is the number of times the key has been previously rotated.

My questions are:

  1. Compromise Concerns: Are there any concerns that if one or more child keys are compromised, it could lead to the compromise of other child keys or even the parent key using this method?

  2. NIST Recommendation: I read in NIST Special Publication 800-108 that in a key derivation hierarchy, child keys should be used either for deriving other child keys or for other purposes (but not both). Is this recommendation due to specific security concerns?

  3. SHA-256 vs. HKDF (HMAC-SHA256): I understand that the "proper" solution is probably to use an HKDF (HMAC-based Key Derivation Function). Is this primarily because it's a standard, or are there specific security issues with using SHA-256 directly for key derivation? As far as I know, SHA-256 doesn't leak additional information from related hashes. Are there any known risks in using SHA-256 in this way?

  4. Differences Between HMAC-SHA256 and SHA-256: In my specific context, what properties distinguish HMAC-SHA256 from plain SHA-256 that are relevant to key derivation? I understand that HMAC includes an XOR of the key material, and the algorithm is: HMAC(K, m) = H( (K' ⊕ opad) || H( (K' ⊕ ipad) || m ) )

  5. Mixing Key and Non-Critical Data: I've read that it's bad practice to mix "key data that is to be protected and other non-critical data (which is often known by the attacker)." (How is HKDF-Expand better than a simple hash?) What are the details of this "badness"? How would it impact the security of the derived keys?

Tldr; I would love to know the specific advantages of using HMAC-SHA256/HKDF over SHA-256 for key derivation as I have outlined, and any risks associated with the way I'm currently doing it.

Thank you!

Note: I apologize if any of my terminology or understanding is incorrect; I'm still learning about cryptography concepts.

1 Answers1

2
  1. For the question's construction, the length-extension property of SHA-256 allows to turn any given child_key for a known version into another child_key for the same (unknown) 256_bit_parent_key and label, and certain other version (strange-looking, longer than the original version by at least 8 bytes, and at least 32 bytes). This is hardly a practical attack. I know no other undesirable property, but see 4 below.

  2. Yes NIST's recommendation that in a key derivation hierarchy, child keys should not be used both for deriving other child keys and other purposes is made for good security reasons. One rational fear is that a derived key intended for the other purpose could be abused into generating values that would be identical to sub-derived child keys, due to the similarity of the crypto primitives used by the unspecified other purpose and the primitives used in the secondary KDF.

  3. HMAC-SHA-256 could be used as a KDF in the application (assuming label is fixed-size) per

    child_key = HMAC-SHA-256( key = 256_bit_parent_key, data = label || version )
    
  4. The advantage of doing as in 3 is that we don't have to worry about length extension attack, and we have a strong security argument that uses weak hypothesis on the compression function of SHA-256; see Mihir Bellare's New Proofs for NMAC and HMAC: Security Without Collision-Resistance, originally in proceedings of Crypto 2006.

  5. I know no concrete attack beside length-extension, but even when it does not apply (e.g. constant-size version) I still recommend HMAC, because of the security argument.

fgrieu
  • 149,326
  • 13
  • 324
  • 622