I collect entropy from the following sources:

  • system_entropy = System provided crypto entropy stream (CryptGenRandom on Windows)
  • user_entropy = User-provided entropy - in a form of a byte stream of serialized random mouse movements, key strokes etc (this is manually entered by the user, similar to how TrueCrypt collects entropy)

To generate a key from these sources, is the following construct appropriate?

my_random_key = HKDF(salt, system_entropy || user_entropy)

Where HKDF is a RFC 5869 construct (both extract and expand steps, but since I don't use "info", just extract is sufficient also) based on HMAC-SHA256.

To my understanding, it should be perfectly fine to just append the user entropy to the system entropy, even under the assumption that the user entropy can be entirely controlled by an adversary, right? Because in that case, the adversary will just destroy the "user_entropy" contribution to the security of the key, but assuming the "system_entropy" is sufficient, then it's ok? In a sense, I assume the "system_entropy" to be already secure, but I want to provide "user_entropy" for additional hardening. So I just want to throw as much random junk at the HKDF as possible.

  • $\begingroup$ This is security theater. First, CryptGenRandom already collects entropy from mouse movements, keystroke timings, etc — and using a much more well-tuned algorithm than you are likely to. Second, if Microsoft is untrustworthy and CryptGenRandom is backdoored, you're already screwed. Just use the output of CryptGenRandom and spend your leftover time addressing attack scenarios with a higher ratio of risk vs mitigation effort. $\endgroup$ – Stephen Touset May 22 '15 at 23:04
  • 2
    $\begingroup$ @StephenTouset: I don't agree. System RNGs have been known to suffer from serious implementation errors (like the Android RNG bug) in the past, not to mention being potentially tempting targets for subversion attacks, and their correct operation is difficult if not impossible for a caller to verify. The safe approach, where possible, is to maintain your own entropy pool, and to treat the system RNG as just another potentially unreliable entropy source for it. $\endgroup$ – Ilmari Karonen May 22 '15 at 23:40
  • $\begingroup$ @StephenTouset The app is multiplatform and so CryptGenRandom is used only on Windows. I have no idea what the library uses on other platforms. The purpose is to give the users an option for additional hardening in case the library does not do a great job at using the system's native crypto RNG. In such case, the method I suggested in my question is appropriate. $\endgroup$ – Paya May 22 '15 at 23:42
  • 1
    $\begingroup$ @StephenTouset In the context of IlmariKaronen's response, I would like to mention the Dual_EC_DRBG CSPRNG backdoor. $\endgroup$ – Paya May 23 '15 at 1:18
  • 1
    $\begingroup$ @StephenTouset Bugs and broken designs are also an option (Android's SecureRandom). Just shrugging and betting everything on MS/Google/Apple that they got it right seems ridiculous, when in fact I can do something about it with no risk of messing up (HKDF). $\endgroup$ – Paya May 24 '15 at 12:07

Yes, that should be secure. It seems however that your problem lies with the secure random number generator and that you are using a KDF to overcome those. Basically you are using a KDF as key generator; no keys are derived from another / master key.

It seems more obvious to use a DRBG / CPRNG (deterministic random bit generator / cryptographically secure pseudo random number generator - there are probably more names) and seed it with random values from the system and the user. After that you can just extract the key bytes, and you would still be left with a (fast) RNG that you can reuse / reseed - something you will likely need later on.

Many API's already provide these out of the box, and usually they are pre-seeded as well, so you may just have to add your user generated entropy to the state by mixing in additional seed data. Nothing stops you from adding HKDF + OtherInfo in addition to the DRBG of course, but that is not required.

  • $\begingroup$ The following answer seems to provide the same conclusion. (linked for reference) $\endgroup$ – Paya May 23 '15 at 12:09
  • $\begingroup$ @Paya I didn't know that that answer existed, but it is nice to know that I'm being backed up by Thomas :) Your idea isn't bad or anything, but if you want to have more random numbers than just for the key (and you usually do) then a PRNG makes a bit more sense. $\endgroup$ – Maarten Bodewes May 23 '15 at 12:20
  • $\begingroup$ It depends. I don't need the "info" just for the extraction, but it seems to come in handy in my specific environment. PRG is certainly an option (as well as PRF like HMAC; and you can build PRG using HKDF anyway as mentioned in the HKDF paper), but I tend to prefer less crypto primitives rather than more, because it makes it less likely to screw up somewhere because various primitives have various assumptions and requirements. HKDF was specifically designed to be pretty much universal solution and has very few assumptions. $\endgroup$ – Paya May 23 '15 at 13:22
  • $\begingroup$ In your solution you are using a key derivation method as key generator. DRBG's, KDF's and key generators are closely related, but they differ on the details. As it seems that your issue is with the random generator, it seems more logical to replace that. Changed the answer a bit to reflect this. $\endgroup$ – Maarten Bodewes May 23 '15 at 20:24
  • 1
    $\begingroup$ I have proposed an "edit" for this answer but was rejected. For that reason, I have to state here that I accepted the answer because of the "yes it is secure" statement and the hint that CSPRNG is yet another option to use. I do not agree with the rest of the first paragraph, but apparently random people who rejected my edit know better. $\endgroup$ – Paya Jun 16 '15 at 16:33

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.