5

Possible Duplicate:
Would it make sense to use Bcrypt and PBKDF2 together?

How does the following password hashing scheme look to you?

iterations1 = scrypt iterations required to spend 50ms on my hardware
iterations2 = pbkdf2 iterations required to spend 50ms on my hardware
ram1 = scrypt suggested default ram requirement
salt1 = urandom
salt2 = urandom
hash = scrypt(pbkdf2(password, salt2+pepper, iterations2), iterations1, ram1, salt1+pepper)
save(username, hash, salt1, salt2, iterations1, iterations2, ram1)

This solution was prompted by my reading of this article: http://www.unlimitednovelty.com/2012/03/dont-use-bcrypt.html.

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?

700 Software
  • 13,897
  • 3
  • 53
  • 82
  • 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. – rook Oct 03 '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 Touset Oct 03 '12 at 19:47

5 Answers5

3

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.

See this answer for more analysis on the subject.

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.

Thomas Pornin
  • 322,884
  • 58
  • 787
  • 955
1

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!

rook
  • 47,004
  • 10
  • 94
  • 182
1

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.

h1 = M_a(m, salt1, params_a)
h2 = M_b(m, salt2, params_b)
hash = h1 ^ h2
save(username, hash, salt1, salt2, params_a, params_b)

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.

Polynomial
  • 133,763
  • 43
  • 302
  • 380
1

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.

Of course, this particular example only occurs if you decide to generate very small output from pbkdf2, but it's an example of how whilst the primitives you use are well vetted, what you're doing with them can be bad. For more on hash truncation, have a read of Does truncating the cryptographic hash make it impossible to crack?.

I'd personally go with either pbkdf2 or scrypt, and not both.

0

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.

Also, scrypt is apparently being considered as an IETF standard, so hopefully it'll get a lot more scrutiny soon.

As for whether you should chain two functions, these questions 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.

Brendan Long
  • 2,898
  • 1
  • 19
  • 27