Skip to main content Link Search Menu Expand Document (external link)

6.5 Hash-Based Key Derivation Function


Hash-Based Key Derivation Functions (HashKDF’s) are keyed hash functions that can be used to deterministically derive multiple keys from a single root key. This can simplify your key management schemes.

Note that if the root key is insecure because it has insufficient entropy, then the derived keys will be insecure for the same reason.

In contrast to Password-Based Key Derivation Functions (PBKDFs) that use slow hash functions, HashKDF’s use cryptographic hash functions that are very quick to execute (i.e. not cpu and memory intensive).

Since user generated password/passphrases typically have low entropy, a quick hash function will make it easier for an adversary to brute force the input space and “crack” the password hashes. For this reason, HashKDF’s are not suitable for deriving cryptographic keys from passwords/passphrases.


Functions

HashKDF(sourceKey []byte, purpose []byte) (derivedKey []byte, err error)

Returns a new 64-byte symmetric key deterministically derived from a 16-byte root symmetric key and human readable explanation of the purpose of the new key.

Parameters
sourceKey ([]byte) - a 16-byte root symmetric key
purpose ([]byte) - arbitrary-length, human readable explanation of the purpose of the newly derived key

Returns
derivedKey ([]byte) - a 64-byte derived symmetric key
err (error)

Example:

sourceKey := userlib.RandomBytes(16)

encKey, err := userlib.HashKDF(sourceKey, []byte("encryption"))
if err != nil { return }

macKey, err := userlib.HashKDF(sourceKey, []byte("mac"))
if err != nil { return }



Notes on Key Reuse

In general, avoid reusing a key for multiple purposes. Why? Here’s a snippet from a post that former CS 161 Professor David Wagner wrote:

Suppose I use a key k to encrypt and MAC a username (say), and elsewhere in the code I use the same key k to encrypt and MAC a filename. This might open up some attacks. For instance, an attacker might be able to take the encrypted username and copy-paste it over the encrypted filename. When the client decrypts the filename, everything decrypts fine, and the MAC is valid (so no error is detected), but now the filename has been replaced with a username.

I’ve seen many protocols that have had subtle flaws like this.

There are two ways to protect yourself from this.  One way is to think really, really hard about these kind of copy-paste attacks whenever you reuse a key for multiple purposes. The other way is to never reuse a key for multiple purposes.  I don’t like to think hard. If I have to think hard, I often make mistakes. Or, as Brian Kernighan once wrote: “Everyone knows that debugging is twice as hard as writing a program in the first place. So if you’re as clever as you can be when you write it, how will you ever debug it?”  So, I recommend way #2: never reuse a key for multiple purposes.

Hopefully this rationale will help you recognize the motivation behind that advice, which might help you recognize when the advice does or doesn’t apply.

Notes on Key Management

In order to simplify your key management scheme, it may be useful to store a small number of root keys, and re-derive many keys for specific purposes “on-the-fly” (a.k.a. when you need them) using the HashKDF function.