Opened 2 years ago

Closed 2 years ago

Last modified 2 years ago

#20138 closed Uncategorized (fixed)

BCrypt effectively limits password length.

Reported by: dstufft Owned by: nobody
Component: contrib.auth Version: master
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Bcrypt effectively truncates the password if it goes over a certain threshold. With the default configuration of Django that seems to be 72 characters. I propose adding a new hash backend that first hashes the password using SHA512. This will not negatively affect the strength of the password hash because bcrypt(sha512(plaintext)) is not insecure as long as sha512 isn't broken. More information: http://security.stackexchange.com/questions/6623/pre-hash-password-before-applying-bcrypt-to-avoid-restricting-password-length .

>>> import random, string, hashlib
>>> from django.conf import settings
>>> settings.configure()
>>> from django.contrib.auth.hashers import BCryptPasswordHasher
>>> password = "".join(random.choice(string.ascii_uppercase + string.digits) for x in range(100))
>>> bcrypt = BCryptPasswordHasher()
>>> bcrypt.verify(password, bcrypt.encode(password, bcrypt.salt()))
True
>>> bcrypt.verify(password[:72], bcrypt.encode(password, bcrypt.salt()))
True
>>> bcrypt.verify(password[:71], bcrypt.encode(password, bcrypt.salt()))
False
>>> bcrypt.verify(hashlib.sha512(password).digest(), bcrypt.encode(hashlib.sha512(password).digest(), bcrypt.salt()))
True
>>> bcrypt.verify(hashlib.sha512(password[:72]).digest(), bcrypt.encode(hashlib.sha512(password).digest(), bcrypt.salt()))
False
>>> bcrypt.verify(hashlib.sha512(password[:71]).digest(), bcrypt.encode(hashlib.sha512(password).digest(), bcrypt.salt()))
False

Change History (4)

comment:1 Changed 2 years ago by dstufft

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

The length of a sha512 digest is 64 bytes so it's within the limit of bcrypt, although even if it wasn't it wouldn't much matter because it retains the property that a small change in the input (the password being truncated) results in a large change in the output.

comment:3 Changed 2 years ago by Donald Stufft <donald@…>

  • Resolution set to fixed
  • Status changed from new to closed

In 25f2acfed0fc110f88abbfffb5c5c62a76670db0:

Fixed #20138 -- Added BCryptSHA256PasswordHasher

BCryptSHA256PasswordHasher pre-hashes the users password using
SHA256 to prevent the 72 byte truncation inherient in the BCrypt
algorithm.

comment:4 Changed 2 years ago by Donald Stufft <donald@…>

In c1d4af6884fbf6c232f6d3fedd168609e0449239:

Merge pull request #958 from dstufft/prehash-bcrypt

Fixed #20138 -- Added BCryptSHA256PasswordHasher

Note: See TracTickets for help on using tickets.
Back to Top