Use SHA512 to avoid bcrypt Truncation
Created originally on Bitbucket by Anonymous
(Imported from Google Code)
donald.stufft wrote:
Bcrypt effectively truncates the password if it goes over a certain threshold (varies based on salt size). With the default configuration of passlib 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 .
You can see an example of what I mean:
>>> import random, string, hashlib
>>> from passlib.hash import bcrypt
>>> password = "".join(random.choice(string.ascii_uppercase + string.digits) for x in range(100))
>>> bcrypt.verify(password, bcrypt.encrypt(password))
True
>>> bcrypt.verify(password[:72], bcrypt.encrypt(password))
True
>>> bcrypt.verify(password[:71], bcrypt.encrypt(password))
False
>>> bcrypt.verify(hashlib.sha512(password).hexdigest(), bcrypt.encrypt(hashlib.sha512(password).hexdigest()))
True
>>> bcrypt.verify(hashlib.sha512(password[:72]).hexdigest(), bcrypt.encrypt(hashlib.sha512(password).hexdigest()))
False
>>> bcrypt.verify(hashlib.sha512(password[:71]).hexdigest(), bcrypt.encrypt(hashlib.sha512(password).hexdigest()))
False