3
$\begingroup$

I'm working on an implementation of Krawczyk and Eronen HKDF from RFC 5869. From Krawczyk's original paper, he identifies four inputs to a KDF in Cryptographic Extraction and Key Derivation: The HKDF Scheme. The four inputs are:

  1. base keying material (secret or seed)
  2. context information (binds security parameters)
  3. public salt (optional, provides uniqueness)
  4. length of derived key

I'm trying to reconcile the differences between a KDF (used in, say, a Diffie-Hellman based scheme) and a PBKDF (used for, say, digesting a password into key material) to provide a common software interface. I think the difference are:

  • KDFs generally enjoy higher entropy seeds, and don't use an iteration count
  • PBKDFs generally lack higher entropy seeds, and use an iteration count to help with some attacks. Sometimes they use a purpose byte, sometimes they use a salt, etc. (The purpose byte seems to be a specialization of contextual information).

Adding PBKDF to the requirements, I think the list becomes:

  1. base keying material (secret or seed)
  2. context information (binds security parameters)
  3. public salt (optional, provides uniqueness)
  4. length of derived key (optional)
  5. iteration count

I want to ensure that the security parameters are well represented in a extensible way, which leads me to two questions:

  1. Is it fair to say a PBKDF is a specialization of KDF?
  2. Will a software interface that support the five parameters above be sufficient?

(Sorry about wandering into software design. I need the help and expertise of folks who understand the cryptography, and not the [purely] software architects).

$\endgroup$
  • $\begingroup$ Note that Diffie-Hellman is key agreement rather than key derivation. It possibly includes a KBKDF scheme, but it isn't one itself. Also note that you may want to check out HKDF which has possibly separate parts for key extraction and key expansion. You may want to somehow reflect that in the API (although having a separate HKDF and HKDF-Extract may do the trick so you don't have to alter the parameters). $\endgroup$ – Maarten Bodewes Jul 6 '15 at 13:55
  • $\begingroup$ @Maarten - yes, thanks. I was referring to the application of the derivation function. For example, IKEv2 uses a KDF because the result of the Diffie-Hellman exchange is not uniformly distributed (so the shared secret cannot be used directly as cryptographic keys). $\endgroup$ – jww Jul 6 '15 at 14:32
1
$\begingroup$
  1. Is it fair to say a PBKDF is a specialization of KDF?

Sure. A PBKDF is a KDF, just one that uses a password/passphrase as the entropy source.

OTOH, a KBKDF (key-based KDF, if you want to call it that) is also a specialization of a KDF. A different specialization, which is why it may not be a good idea to treat them as a single thing.

  1. Will a software interface that support the five parameters above be sufficient?

There are a couple of common parameters that are missing:

  1. Many password hashing functions have a second cost parameter indicating how much memory will be used. (E.g. scrypt, most of those from the currently running Password Hashing Competition.)

  2. Another relatively common parameter is a pepper. You can just include it as part of the salt if needed, but then the same is true for your context information parameter.

I also don't think your parameters, even with the above additions, are the best way to define such an interface.

For one, I don't think a salt should ever be left out, so I don't see why it should be optional.

For another, there is a significant difference in how a key derivation function is normally used, compared to how a password hash is used:

  • With a key derivation function, you are going to need a key of a certain size as output.
  • With a password hash it is useful to get an opaque return value that can be passed as the only additional parameter into a verification routine:

    verify(password, combined_hash)
    

    (Cf. Modular Crypt Format.)

    This way the iteration count, salt, etc. is easily stored with the hash, and different hashed can have different parameters, allowing one to upgrade the strength with time as attackers' computational power increases.

$\endgroup$
  • $\begingroup$ "... I don't think a salt should ever be left out, so I don't see why it should be optional..." - OK, I have to be careful here. First, it could reduce to me just bike shedding. Second, some standards have already made that call. $\endgroup$ – jww Jul 6 '15 at 14:35
  • $\begingroup$ "... opaque return value that can be passed as the only additional parameter into a verification routine..." - OK, this is interesting. One of the ideas I have been contemplating is a base class of KeyDerivationFunctionParameters, and each KDF can define their own requirements. That even tidies up KDFs like Scrypt, and provides the future extensibility I hope to achieve. I've resisted it because I was trying to keep changes to a minimum, and I did not want to add five or six new C++ classes. $\endgroup$ – jww Jul 6 '15 at 14:41
  • 1
    $\begingroup$ That's basically how Java solves this, injecting through a parameters instance and then validating if the parameter class is supported. That doesn't preclude a relatively general implementation of the parameter interface with just the commom options of course. $\endgroup$ – Maarten Bodewes Jul 6 '15 at 15:38
  • $\begingroup$ Thanks Marteen. I think its quickly converging on a Parameters class. My next step was precisely what you called out - take a look at Java's architecture, and see what they do. $\endgroup$ – jww Jul 7 '15 at 2:59
  • $\begingroup$ Thanks Otus, Maarten and others. We decided on a simpler interface, where the particular's scheme's parameters are passed in through another object (KeyDerivationParams class). $\endgroup$ – jww Jul 9 '15 at 10:53

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.