11

I want to allow any-sized passwords to be allowed to be submitted. I currently use bcrypt as a key derivation function for passwords, however I have realized that it has a maximum input length of 72.

Because of this, I would like to sha512 passwords before passing them to bcrypt, allowing any-sized passwords to register, because it's my understanding that sha512 outputs 64 bytes.

Is this OK practice? I've heard that mixing and matching hashes, or "creating your own crypto" is bad practice, but this seems like a viable workaround to the hard limit.

Thanks.

InvokeStatic
  • 133
  • 1
  • 5

4 Answers4

16

Hashing passwords with a decent, secure hash function before pushing them into bcrypt is a reasonable and secure way to keep all the goodness of bcrypt, and additionally support passwords of arbitrary size.

You still want to exercise caution about some practical details. In particular, many bcrypt implementations expect a password, i.e. a sequence of characters, terminating with the first byte of value 0x00. The output of SHA-512 is binary and thus may contain some bytes of value 0x00. For instance, 1/256th of all passwords will yield a hash value which begins with a byte of value 0x00, that a string-based bcrypt instance will understand as equivalent to an empty password. This is not good...

The solution is to use a deterministic bytes-to-characters encoding, e.g. Base64. Since this implies some size extension, SHA-512 will no longer be adequate (Base64 turns 64 bytes into 88 characters, more than the 72 limit of bcrypt). Therefore, use SHA-256: the 256-bit output (32 bytes) will be encoded by Base64 into 44 characters, and that will be fine with bcrypt.

(The 512-bit output size of SHA-512 is utter overkill anyway. SHA-256 is good enough.)

Thomas Pornin
  • 322,884
  • 58
  • 787
  • 955
  • 2
    I would go with SHA-384 or use SHA-512 and truncate the base64 output to 72 characters. It may be overkill, but as long as the SHA step is faster than the bcrypt step, there is little reason to go down to only 256 bits. – kasperd May 06 '15 at 15:45
  • If you're looking for the answer to "But how much work factor for bcrypt?" then look here https://security.stackexchange.com/a/17238/69959 – cottsak Mar 19 '18 at 04:50
1

As far as I am aware prehashing the user input with a cryptographic hash function and then hash the result with a password hash function is accepted.

Mozilla suggests a hmac+bcrypt, if you choose SHA512 for the HMAC that should be fine. (I believe SHA512 is the same kind of overkill as AES256, so you could save some CPU cycles by using SHA256 without sacrificing security)

The Makwa password-hashing function, which is a candidate in the Password Hashing Competition by Thomas Pornin actually has support for both pre- and post-hashing.

Darsstar
  • 266
  • 4
  • 8
0

SHA-256 is more than enough.

It addresses the 72 byte limit for input size, and would avoid the length overflow bug (length over 255 characters reduce input to 0 and increment again) that two implementations were known to have and since patched in 2014(OpenBSD) and 2020(NodeJS).

Even if your password entropy is higher than 256 bits, the bcrypt output is 184 bits. Despite both levels of entropy being infeasible to attack, 184-bit is less work than 256-bit or greater.

0

This will not weaken your passwords nor add addtional security. The entropy, even after truncation for longer passwords, will still be high enough. Actually PBKDF2, which is also often used to hash passwords, does something similar when the derived key from a password exceeds the blocksize.

Lucas Kauffman
  • 54,229
  • 17
  • 113
  • 196