-
Notifications
You must be signed in to change notification settings - Fork 210
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for bcrypt_sha256 #297
Comments
Hi @Jonny007-MKD thank you for bringing this up. Let's go down that rabbit hole, if you don't mind, because this is an important topic. While the bcrypt specification calls for 72 (or 71+null termination) bytes, these are not guaranteed in any implementation and it is safer to assume that the key part is limited to about 54 bytes. Since each byte it encoded using two bytes (hexadecimal), our worst case scenario is that we encode 27 bytes. An advantage that bcrypt holds over pure key derivation algorithms is that it is both RAM heavy, which is not very GPU friendly, but also Blowfish is not easy to vectorize (unlike SHA256) OK, so... why not wrap a SHA256 hash in our bcrypt call? A way to mitigate shucking is to "pepper" your sha256 hash before hashing it again. Unfortunately, if your database is stolen, your pepper may come along if it lives anywhere near it. So, back to 176 of entropy. After all the previously mentioned caveats, it is not so bad. I am open to further discussion on what the best approach would be. |
Hi @Fusion, I am not a password hashing specialist. I read about this on the python passlib manual page. Now I spent some time, though, to understand the issues :) These are the sources I used:
I'll summarize the hash shucking first, in case you don't want to spend 40 minutes watching the video. It's worth it, though! Hash shucking means:
What can the attacker do with this information? In his talk Sam Croley makes a small statement at the end (minute 42): this hash shucking does not work, if the inner hash was salted in the first place. That's exactly what is implemented in passlib's bcrypt_sha256 (version 2): It does not use plain SHA256, but HMAC-SHA256 with the same salt that bcrypt gets. Another problem that the OWASP cheat sheet mentions: One must not feed raw bytes from hash functions into bcrypt, as hashes may contain OWASP is discouraging exactly this solution, though 🤔 and I don't want to recommend to ignore OWASP recommendations, even though I don't agree with them. |
BCrypt only hashes the first 72 Bytes of a password, with UTF-8 this makes up to 72 characters, only. That's why BCrypt-SHA256 was created:
https://passlib.readthedocs.io/en/stable/lib/passlib.hash.bcrypt_sha256.html
https://gitlab.com/gitlab-org/gitlab/-/issues/220580
The text was updated successfully, but these errors were encountered: