Skip to content
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

Passwords shouldn't be limited to 72 characters #5307

Open
rugk opened this issue Nov 5, 2020 · 7 comments
Open

Passwords shouldn't be limited to 72 characters #5307

rugk opened this issue Nov 5, 2020 · 7 comments

Comments

@rugk
Copy link

rugk commented Nov 5, 2020

Current behavior

Due to bcrypt passwords are limited to 72 bytes/characters.

Expected behavior

Possibly pre-hash the password before putting it into bcrypt.
See downstream issue mastodon/mastodon#13152 for details why it is a problem in Mastodon.

Note: I have no knowledge of Ruby, I'm just creating this issue.

@tribela
Copy link

tribela commented Mar 3, 2021

72 Bytes actually. UTF-8 character encodes into 1~4 bytes

@drakmail
Copy link

drakmail commented Dec 8, 2021

Maximum password length should be limited because of computation time of password hash. It takes 15-150 seconds of uninterruptible bcrypt hash calculation if password have ~1024 characters length.

@pboling
Copy link

pboling commented Jan 24, 2022

With https://github.com/heartcombo/devise-encryptable you can use other encryption tools, such as argon2, which will hash up to a 4Gb input string (not recommended, it might let out the magic smoke!).

@xanderificnl
Copy link

Anyone who is (or is considering) pre-hashing should be aware that OWASP considers it a dangerous practice that should be avoided.

@pboling
Copy link

pboling commented Feb 14, 2022

@drakmail The bcrypt algorithm actually ignores the characters after the first 72 bytes, so there is no way to hash a 1024 character password with bcrypt. Perhaps you meant another algorithm?

@drakmail
Copy link

@pboling when user sends a long password (tens of thousands characters) the rails server hangs for several seconds consuming 100% CPU

@xanderificnl
Copy link

@pboling when user sends a long password (tens of thousands characters) the rails server hangs for several seconds consuming 100% CPU

Are you using the bcrypt-ruby gem? That's the default in Rails' Gemfile. Starting at 512 bytes it should raise BCrypt::Errors::InvalidHash, for instance:

3.1.0 (mbb)[1] » BCrypt::Password.create('a'*512)
BCrypt::Errors::InvalidHash: invalid hash

So bcrypt shouldn't return a hash for a password containing 1024 characters. The hang-up you're describing is most likely related to ruby itself, in my IRB console, this does cause a (temporary) hang up:

# only do this if you don't mind hangups. 
3.1.0 (mbb)[2] » 'a'*99999999999999

Back to the main point; the limit of bcrypt is 72 bytes, which effectively means a password containing only a's of 72 bytes is equal to 73 bytes of a's ad infinitum. To illustrate this:

3.1.0 (mbb)[3] » b72 = BCrypt::Password.create('a'*72) # 72 bytes of a's
=> "$2a$12$g2IH91mSXl6Xww/RfvVI6.l3g9fHL.KtD5Xg4bhoVE5l6cx3hQRrC"
3.1.0 (mbb)[4] » b72 == 'a'*73 # <-- not the same password
=> true
3.1.0 (mbb)[5] » b72 == 'a'*74 # <-- not the same password
=> true
3.1.0 (mbb)[6] » b72 == 'a'*100 # <-- not the same password
=> true

In the linked thread in a mastodon repository, a case is made for seemingly small passwords exceeding 72 bytes. It's a valid case and point. Truncating passwords should be avoided. So, in case anyone also hit this issue, here are a couple of ways to handle this issue:

  • You can refuse passwords longer than 72 bytes. This isn't a great way.
  • Use a different algorithm, i.e. Argon2i or Argon2id.
  • Use BCrypt for passwords up to 72 bytes and switch over to Argon2i(d) for passwords longer. (bcrypt has been around way longer than argon2 and has proven itself; so thats something to keep in mind.)

In any case, password fields should have a limit to avoid bad actors from DoS'ing your service and this limit should be enforced before you hash the password. Especially when using a slow algorithm (i.e. bcrypt, argon, etc.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

5 participants