I need to store passwords for a web application, and was looking at Bcrypt for a possible solution. After some research, it appears only the first 72 bytes influence the final hash output. While it is possible for the application to limit input to 72 characters, this hurts users with password managers that produce very long passwords.
While it is well known that hash1(hash2(x))
only serves to increase collisions, there doesn't seem to be much information about the implications of using bcrypt(hash1(x))
, as indicated by this answer.
First idea
If the password p
is p > 72
bytes, SHA512 [64 bytes] the password and then Bcrypt the hash.
Possible cons:
- hashing a hash
- the input to Bcrypt is only ever as big as the output of the hash function (64 bytes)
Second idea
If the password p
is p > 72
bytes, calculate the hash with (pseudo-code):
bcrypt(p[0:8] + sha512(p))
This Bcrypt's the concatenation of the first 8 bytes of the password (which is 72 - 64, where 64 is the bytes of the SHA512 hash) with the SHA512 [64 bytes] digest of the entire password. By this, the Bcrypt function hashes an entire 72 bytes, instead of just 64 like with the plain old SHA512 [64 bytes] hash.
Probable pros:
- full 72 bytes are Bcrypt'ed
- does not Bcrypt just a hash; this may make it so that if a collision is found in the SHA512 [64 bytes] hash, there are still a leftover of 8 bytes of entropy needed to crack the password
Possible cons:
- still involves partially hashing a hash
I'm under the impression that the second idea is the best and most secure way to go, but I'm not sure if that, at all, decreases security for passwords > 72 bytes in length. I'm asking if there are any obvious (or non-obvious) security implications with choosing this method.