Code

Opened 13 months ago

Closed 13 months ago

Last modified 13 months 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

Attachments (0)

Change History (4)

comment:1 Changed 13 months 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 13 months 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 13 months ago by Donald Stufft <donald@…>

In c1d4af6884fbf6c232f6d3fedd168609e0449239:

Merge pull request #958 from dstufft/prehash-bcrypt

Fixed #20138 -- Added BCryptSHA256PasswordHasher

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.