Opened 12 years ago

Closed 12 years ago

Last modified 12 years ago

#20138 closed Uncategorized (fixed)

BCrypt effectively limits password length.

Reported by: Donald Stufft Owned by: nobody
Component: contrib.auth Version: dev
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 by Donald Stufft, 12 years ago

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 by Donald Stufft <donald@…>, 12 years ago

Resolution: fixed
Status: newclosed

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 by Donald Stufft <donald@…>, 12 years ago

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