4
$\begingroup$

On the following site:

https://paragonie.com/blog/2015/04/secure-authentication-php-with-long-term-persistence

when talking about the dangers of using bcrypt it states:

There is a nontrivial chance that one of the raw bytes in the hash will be 0x00. The sooner this byte appears in the string, the cost of finding a collision becomes exponentially cheaper.

I am not fully understanding what this means and how 0x00 would result in finding a collision sooner than any other hex digit. Can someone explain this more clearly to me. I also do not understand why sending it through base64_encode would make a difference as the password will still be the same and can be decoded with base64_decode.

Also, on this page it states that using base64_encode will get around the 72 character limit of bcrypt. However, if the bcrypt algorithm limits any input to 72 characters why wouldn't it also limit the base64_encoded string to 72 characters?

$\endgroup$
8
$\begingroup$

In many cases, 0x00 is treated as end of string. That is where the problem comes into play. So if I passed password\x00defgreallylongpassword into bcrypt, the password would be terminated after password due to the null byte. That is a very insecure password and can easily be found with a dictionary attack.

No one types null bytes into a password field, however. Where the blog post says this can occur in practice is if you first hash the password, then run it through bcrypt. There is a chance that the hash digest will have a null byte in it, which will cause the bcrypt code to truncate it.

The poster gets around this by suggesting that you base64 encode the hash of the password before feeding that to bcrypt. The base64 encoding will not have null bytes.

This hash then bcrypt construction has been proposed as a way around the 72 character limit of bcrypt. That said, I agree with this answer on our sister site. If you are using bcrypt for values that you expect might be larger than 72 characters, you are probably not using bcrypt for its intended purposes and should rethink what you are doing.

$\endgroup$
  • $\begingroup$ I've heard of a system with a worse problem: reportedly, the bcrypt hash was stored in binary, and truncated at the first zero in that binary. Thus one in about 256 accounts was accessible with about one in 256 random passwords. $\endgroup$ – fgrieu Mar 3 '16 at 17:25
  • $\begingroup$ Doesn't surprise me at all given the many encoding/decoding errors that I see, probably make up for the bulk of crypto problems (of the uninitiated). Of course this problem wouldn't be present in any self respecting library and/or language that simply treats the input to bcrypt - the algorithm - as bytes. $\endgroup$ – Maarten Bodewes Mar 3 '16 at 17:52
  • $\begingroup$ @mikeazo Thanks, how does the base64 string not also get cut off at 72 characters? $\endgroup$ – kojow7 Mar 3 '16 at 17:57
  • $\begingroup$ @kojow7, it would. But the point is you hash to a fixed size first, say 256 bits, which is 32 bytes (characters). A base64 encoding of 32 bytes will not be larger than 72 bytes. $\endgroup$ – mikeazo Mar 3 '16 at 17:59
  • 1
    $\begingroup$ @kojow7 to quote the blog: "The solution, therefore, would be to pass the raw SHA-256 hash outputs through base64_encode() before passing them to bcrypt" $\endgroup$ – mikeazo Mar 3 '16 at 18:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.