This is to allow me to take advantage of the great features of scrypt, as well as allowing me to take advantage of the time tested security of pbkdf2. Is it a reasonable approach? Do you think I should limit this to only use one of the two algorithms, or do you think I should only use 1 shared salt for both algorithms?

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

1

I find that people who don't understand security tend throw all the security systems they have heard about without understanding that this combination doesn't improve anything. When auditing a code base, I see this as a weakness and it encourages me to find more complex flaws in a given system.
–
RookOct 3 '12 at 19:04

2

Put another way, if there was research to support this approach and enough security professionals encouraging it, there would already be libraries to abstract away the task for you. Since there is not, you are by definition inventing your own cryptography.
–
Stephen TousetOct 3 '12 at 19:47

5 Answers
5

Combining dilutes your advantage. This slow-hashing business is about fighting the attacker on equal grounds, your CPU against his CPU; scrypt further equalizes things by optimizing the password hashing for the kind of hardware that you use (a PC) instead of letting the attacker optimize things on his side with non-PC hardware. If you spend half your CPU budget on PBKDF2, than that half is a bit wasted, since the attacker can thoroughly optimize PBKDF2 with a GPU.

The article you quote seems to be of dubious quality. For instance, it badmouths bcrypt on the basis of alleged weaknesses on 3DES -- but bcrypt is not at all about 3DES, and there is no known attack of academic cost "80 bits" on 3DES either. I suggest that you do not trust that article too much.

I don't see any point in using scyrpt with pkdf2. scrypt allows you to define the amount of CPU and Memory required to produce a particular hash. In order to do this, scrypt is behaving much like pbkdf2, in that it is cycling over a hash function to produce this output.

pkdf2+bcrypt is a great password storage method, but I think scrypt better than this because you can also increase memory usage!

Well, for starters, you're missing an argument to pbkdf2 - that is, the length of the output. This is quite literally controlled by truncating to n blocks of the input function after it has gone through the pbkdf2 algorithm

The reason I bring this up is that combining the two functions like this could potentially be your undoing. If, let's say hypothetically, you decided to generate just one byte of output from pbkdf2. Great, now you've got 2^8 possible inputs to scrypt. Even with expensive requirements, 256 possible inputs isn't hard to brute force. Then, from any given password hash, you can go back to the post-pbkdf2 state.

The fact that asking for one byte of output from pbkdf2 truncates the hmac presents an interesting possibility - you no longer need to find a collision over 2^160 (for pkcs#5 with hmac-sha1) but just 2^8. In English, you don't need to find the password, you need to find a password that works.

This doesn't provide as much of a benefit as you might think. You're just as vulnerable to any type of attack on inner hash which reduces its security significantly, because it allows manipulation of the data in a way that makes the inner hash abnormally. A better solution is to xor the outputs of the two hashes.

This ensures that you have the security of at least the strongest hash, without the afforementioned downsides. Keep in mind that this is only true for hashes with entirely different constructions, which results in an ill-defined security "proof" (or lack thereof).

Either way, it's probably not a good idea to combine functions, because there's no guarantee that they'll interact in the way you expect. Cryptographic functions are mostly a house of cards and, as Thomas Pornin said so eloquently, a prayer to $DEITY. Mixing them together causes unknowns to appear. Whilst it's difficult to say that it's flawed or stronger, it's generally a case of hoping for the best.

However, this all assumes that your premise is valid. You're better off using scrypt, which provides the same strengh as PBKDF2 and bcrypt combined, with extra features designed to make GPU and FPGA acceleration very inefficient and difficult.

Regarding PBKDF2 vs bcrypt: bcrypt is harder to attack via dedicated hardware, so should be significantly stronger. It's possible that bcrypt could have problems, but it's based on a well known function and hasn't seemed to have any problems in the 13 years its been around.

PBKDF2 is a standard with more scrutiny, but it's also much easier to attack via dedicated hardware, so you could make the case that its security is known to be broken in a way that bcrypt isn't (yet).

In the same vein, bcrypt is much easier to attack via dedicated hardware than scrypt. The difference is that scrypt was presented 3 years ago, vs 13 for bcrypt.

As for whether you should chain two functions, thesequestions answer it better than I could (the second is about bcrypt + PBKDF2 but it doesn't matter what the functions in question are):

So you do not get something stronger that way; instead, you get a security level which is an average of what you would have got with Bcrypt alone, or with PBKDF2 alone.

Combining two hash functions or similar functions together is good to avoid a catastrophic failure, if one turns out to be broken; but, assuming that both Bcrypt and PBKDF2 are strong, and the question is mostly about performance (both bcrypt and PBKDF2 are about making exhaustive search slower, so this is all about performance). For optimal slowness, combining bcrypt and PBKDF2 is not a good idea.

It's worth noting that "catastrophic failure" seems pretty unlikely. I mean -- MD5 is known to be broken, but PBKDF2 using MD5 is still "good enough". Sure it's too fast, but you can turn up the iterations. Sure it's not good at collision resistance, but that's unlikely to be a problem with reasonable length (less than a hundred character) passwords.