# chaining multiple key derivation functions together

I was looking at PBKDF2, bcrypt and scrypt as options for key derivation; and would like to try using them all together in order to get the cryptographic strength of the strongest one (which seems to be scrypt so far unless something novel is discovered). My first thought was to apply the first kdf to the password, then apply the second kdf to the obtained key (using it as the second password), and then the third. Is there something inherently wrong with this?

I saw a different approach posted by user perseids here:

http://www.unlimitednovelty.com/2012/03/dont-use-bcrypt.html

I quote: "Derive p_1 = HMAC(Salt1+"PBKDF2") with key sha256(p), p_2 = HMAC(Salt2+"bcrypt") with key sha1(p) and p_3 = HMAC(Salt3+ "scrypt") with key sha1(p). Derive key k1, k2 and k3 by using the key derivation function PBKDF2, bcrypt and scrypt respectively, each of them using 1/30 seconds CPU time with input p_1, p_2 and p_3 respectively. Compute the key (or database reference entry) as sha256(k1+k2+k3). Here "+" designates the concatenation of byte arrays. "

So basically the 3 kdfs are applied in parallel, and the resulting keys are concatenated and then hashed together. What do you guys think about this one? Is this obviously superior to just applying the multiple kdf "in series"?

Also, what are considered the most reliable and well scrutinized C or C++ implementations of bcrypt and scrypt (I found pbkdf2 in crypto++ and botan). Edit: I guess if they produce the right results, then they are reliable, so one point would be that they are well tested, but also what would be important is that they are implemented reasonably efficiently, so they don't give you a false sense of security (e.g. taking long time to compute, when in fact an attacker could take much less time to compute the same with a better algorithm, even without specialized hardware).

## 1 Answer

Yes, there's an issue: you're adding needless complexity, which gives you absolutely no benefit.

The whole point of a PBKDF is to be slow; passwords are low-entropy, and the only way to mitigate brute-force is to make it take time to compute hashes. It can't take too long to log in, so you have to balance "fast for a user" and "slow for an attacker." Attackers use hashes differently than users; an attacker will be trying many, many, many combinations, possibly on specialized hardware, while a user only tries one password at a time.

The trouble with combining hashes is that you only have a certain amount of time and resources you can give your hashing process. If you take 200ms for PBKDF2, 200ms for bcrypt, and 200ms and 16 MB for scrypt, your system takes 600ms to compute a hash. Suppose that PBKDF2 hardware implementations are \$1.00 per 100 threads of PBKDF2; bcrypt ones are \$50.00 per 100 threads of bcrypt; scrypt ones are \$100 per 100 threads of scrypt (these numbers are wholly made up). Then an attacker can attack 300 hashes at once for a cost of \$151; this will check a new hash every 2ms on average. If you just used scrypt with 600ms and 16 MB required, then an attacker would need 300 scrypt threads to get that throughput; this is \\$300.

Basically, the issue with combining them is that you're shifting hash time from a stronger algorithm (where it's expensive for the attacker to do things faster than you) into a weaker algorithm (where it's cheap for the attacker to do things faster you).

• cpast - thank you for your input, the assumption though is that it is not known which one is the strongest. Although it does look likely that scrypt is , since it is relatively new, mathematical discoveries could tehoretically be made that would reduce its complexity, and/or make the time+RAM that it takes less than linear with the number of rounds. Same goes for the others but at least they've been around for longer. I understand the tradeoff, just trying to protect against the unknown. My question, still, is, how would combining them in series vs in parallel compare? Mar 22, 2015 at 20:33