sha256 password before passing to bcrypt to avoid issues with 72 bytes truncation for passwords#5807
sha256 password before passing to bcrypt to avoid issues with 72 bytes truncation for passwords#5807le0pard wants to merge 1 commit intoheartcombo:mainfrom
Conversation
086ca31 to
d54b09b
Compare
test/encryptor_test.rb
Outdated
| test 'digest/compare support old bcrypt only passwords' do | ||
| password = 'example' | ||
| password_with_pepper = "#{password}#{Devise.pepper}" | ||
| old_hashed_password =::BCrypt::Password.create(password_with_pepper, cost: Devise.stretches) |
There was a problem hiding this comment.
Excuse me for interrupting, I thought a half space was needed.
suggest
old_hashed_password = ::BCrypt::Password.create(password_with_pepper, cost: Devise.stretches)
…s truncation for passwords
d54b09b to
1c5203e
Compare
|
I think we should ensure passwords are not longer than the max BCrypt supports, rather than trying to work around it? I can't think of any immediate issue running through SHA would cause off the top of my head, but that doesn't mean it won't open a can of worms to bite us in the future. |
|
You can read about this here - https://security.stackexchange.com/questions/92175/what-are-the-pros-and-cons-of-using-sha256-to-hash-a-password-before-passing-it TLDR: SHA-256 allows for avoiding length constraints where entropy would otherwise be lost Passlib in python do the same - https://passlib.readthedocs.io/en/stable/lib/passlib.hash.bcrypt.html#bcrypt-password-truncation Possible alternative, move to Argon2, which not have such limitations, but this will require to add another dependency and leave bcrypt for backward compatibility |
|
https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html - right now owasp for usage Argon2, bcrypt is way to hash passwords for legacy systems. But yes, we can limit to 72 bytes (it will be less characters, because of Unicode) passwords and raise error Or I can create Argon2 usage PR, with fallback to bcrypt, but this will require major release version for devise |
|
@le0pard thanks for the links, I'll read up to understand the implications a bit better, but this called my attention at a first glance: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pre-hashing-passwords-with-bcrypt
Re Argon2: something I'd like to support at some point, yes. Whether it'd become the default or not, not sure, but probably yes, eventually. (it doesn't need to be the default from the get go) |
|
@carlosantoniodasilva that is why I am using Ok, so what is preferable for now - such fix or maybe better prepare PR for Argon2 (which is not default and can be activated by option, which may be will be default in future)? |
|
Makes sense, but I still want to catch up a bit on that reading before applying anything, as it is a more complex implementation to keep track of under the hood. I think for now I'd rather enforce the 72 bytes limitation if using BCrypt (I imagine for the majority of users this won't be a big deal), and then we can start working towards offering Argon2 as an opt-in to swap with BCrypt. (in case people need more than 72 bytes) (with a potential "rolling" option for people to migrate over time, e.g.: https://github.com/heartcombo/devise-encryptable/pull/19/changes which I haven't merged yet.) |
|
ok, so we can have something like this validation: But again, not sure it will be not broken changes (maybe not critical, but still) |
|
It will probably be potentially breaking/annoying, but not one that warrants a major imo (perhaps / probably minor). And we should probably warn if the password length validation is larger or something, to give people a hint. (I understand that length validation != bytes validation, and we'll have to enforce bytes validation, but it's something...) I can also add a warning when installing that new version of Devise if necessary (via the gemspec), plus the changelog, so not too worried about that. |
|
ok, so should I prepare this changes is different PR for validation or you will do this @carlosantoniodasilva ? I can handle good amount, except maybe "add a warning when installing that new version of Devise" - not sure about this, because it maybe busy with turbo already :D |
|
ok, thanks. closing this one |
More info: bcrypt-ruby/bcrypt-ruby#283
Reproduction:
All return
true, soPassword 1:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1Password 2:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2These two users can login to each other's accounts because brcypt caps hashing to the first 72 bytes.
As solution - hash password to sha256, so it always will be smaller, than 72 bytes. Added fallback for old passwords.
In this case we can reject #5806