Let's temporarily work upon the assumption that proper KBKDF functions do not exist, for the sake of argument.
Would keccak256 be a secure choice for a KBKDF that derives 256-bit keys from a 256-bit master secret $k_{256}$ with an arbitrary-length derivation path $p$? And is this true in general for hash functions that have the properties outlined below?
My thinking is:
- The input $k_{256}$ is high entropy already (we assume we have a cryptographic-grade key as a starting point), so using a relatively fast function like keccak256 is not a problem
- If we compute $keccak256(k_{256} || p)$ (or in principle any other construction), we get by definition something of the same or lower entropy level, but I understand that a general goal for hash functions is to avoid discarding to the highest possible extent (i.e. minimize collisions)
- $keccak256(k_{256} || p)$ is not susceptible to length-extension attacks, so $p$ does not need to be fixed-length if we want to avoid traditional MACs' nested approach
Is this a correct assessment? If it is, then:
- What is the advantage of using e.g. HKDF over using keccak256 or an hashing function with similar properties, given that we assume $k_{256}$ to be uniform and we don't need any form of stretching?
- Does this hold for other hashing functions for which the above assumptions hold? E.g. is it also true that for 256 -> 256 derivation, BLAKE2s is sufficient (as opposed to e.g. BLAKE2X or BLAKE2s-based HKDF)?
Taking this further, wouldn't using HKDF be potentially worse than just using keccak256 or a similar hashing function? Since HKDF assumes that it's extracting entropy from a potentially non-uniform input, would it retain more, less, or the same amount of entropy from an input compared to keccak256, or a similar hashing function?
Finally, as an extension to the question, would all of the above still hold true for key lengths lower than 256 bits? E.g. deriving a 128-bit key from a 128-bit master secret $k_{128}$ as
$truncate(128, keccak256(k_{128} || p))$
My thinking is that this hold, under the assumption that the entropy is evenly present along the entire output, and as such the truncation discards none to a minimal amount of entropy. However, I have noticed that the prominent Noise protocol framework does truncate the output of its HKDF function in the MixKey
operation, but that's only to generate a key that is never used as an input for key derivation. Instead, it keeps a separate hash-length chaining key that is continously mixed to derive the next chaining key, while never being truncated. Why is this mechanism needed? Is it to minimize that minimal amount of entropy which could be still discarded by the truncation?