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.