0
$\begingroup$

I have to generated a secure key from some meta data and a password, and I'm free to choose among a dozen of key derivation functions (KDFs). The problem is, I'm not too happy with either one. Some are well known and proven to be secure but they are not expensive enough to really survive a massive brute force or dictionary attack (e.g. bcrypt or PBKDF2). Others claim to be prepared against such attacks, but they are not so well known yet, they are rather new and have not been studied for years, so it's still possible that someone finds a weak spot or a backdoor (e.g. scrypt or Argon2, and scrypt already turned out to be weaker than people initially thought it would be). Using just a single KDF seems out of question to me if you really need secure and hard to attack keys, it's like betting all your money on a single horse: if it loses, you've lost it all.

Remembering the Intel random number generator fail? The Linux kernel hackers said that this problem doesn't really affect the random number generator of the Linux kernel as the CPU generator is only one among many random sources and

Random + Not-Random = Random

so as long as at least one of these sources is able to provide good random numbers, the result is still random, even if an attacker can control the quality of the other sources.

Wouldn't the same apply to mixing derived keys?

Good-Key + Bad-Key = Good-Key (???)

So if I use two derivation functions, one that is known to be secure but a bit weak and one that is very strong but not (yet) known to be secure, wouldn't this lead to better keys than just relying on one method?

And if this assumption is correct, how would I mix the two keys? What would be a good, secure method for that? Treating them as big numbers and then just doing add + modulo? Concatenating them and hashing the result? I'm a bit afraid that using a bad "mix function" will weaken the final result when the mix function becomes the weakest link of that chain.

Update

Mixing the keys is just "an idea", of course, maybe instead of mixing it would be better to use the output of one KDF as the input for the other one. At least that makes the whole thing less parallelize-able and thus harder to attack for number crunchers. But maybe that's not true, maybe it makes it much easier to attack if one of both KDFs fail as now you have a chain and as I said above, a chain is often only as strong as its weakest link. Also interesting, if I use two KDF, A and B, and it is more likely that A is weak than B, would it be better to do A(B(x)) or B(A(x))?

Another idea I had was using an HMAC for mixing, one key would be the data and one key would be, well, the key. Calculating an HMAC if you only have one of both, the key or the data, is still extremely hard, so if just one KDF fails, that shouldn't be a problem. Of course, the final key depends on the security of the HMAC function but the HMAC algorithm is in use for decades, one could say it has been proven to be secure. And that is true even when using such a poor hash function as MD5. MD5 itself has been broken long ago, it's totally useless for cryptography today, yet, so far nobody ever managed to break HMAC-MD5, which means HMAC is a good function and maybe HMAC-SHA2 would be a good way to mix two keys?

This seems such an obvious problem that I'm pretty sure all these questions have been asked before and even answered before, I'm not here to invent anything new, no way(!), I just haven't been able to find the answers, that's what I'm here for, finding answers.

$\endgroup$
4
$\begingroup$

This answer is part answer, part comment requesting refinement of the language in the question.

There is an assumption in the question that is not necessarily valid.

Using just a single KDF seems out of question to me if you really need secure and hard to attack keys

There is a counter example to the intuition that using more functions will make it more difficult: Suppose you are allotted 1 second of time per evaluation of the key derivation function. If you use scrypt for .5 seconds and then bcrypt for the next .5 seconds (or vice versa), your key derivation function uses less memory then just using scrypt for the entire 1 second. So if memory hardness was the goal, then mixing two functions does not necessarily improve security. Which leads to the next point:

So if I use two derivation functions, one that is known to be secure but a bit weak and one that is very strong but not (yet) known to be secure, wouldn't this lead to better keys than just relying on one method?

First, there is a contradiction: What exactly is a method that is known to be secure, but is weak? How can we know it's strong if we do not know it is secure? If "strength" is somehow separate from "security", your definitions for the two terms would be appreciated.

Secondly, you have to define "better" keys: better in regards to what?

How would I mix the two keys? What would be a good, secure method for that

You have to define "secure": Combining hash functions is not trivial.

If you can assume that at least one of the outputs is psuedorandom, then there is little reason not to use the simplest method possible, namely, XOR. The output of $x \oplus y$ is at least as random as the more random of the two (otherwise a OTP would not work).

Unless for some reason, you want order to matter, then you could use a non-commutative operation such as concatenation and hashing. Unless you have an explicit reason for needing the properties of some other mixer, it is probably best to use the simplest tool for the job.

$\endgroup$

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.