Fixed #24115 -- Allowed bcrypt hashers to upgrade passwords on rounds change.
Thanks Florian Apolloner for the review.
This commit is contained in:
parent
e4cf8c8420
commit
b86abbceb9
|
@ -337,6 +337,10 @@ class BCryptSHA256PasswordHasher(BasePasswordHasher):
|
|||
(_('checksum'), mask_hash(checksum)),
|
||||
])
|
||||
|
||||
def must_update(self, encoded):
|
||||
algorithm, empty, algostr, rounds, data = encoded.split('$', 4)
|
||||
return int(rounds) != self.rounds
|
||||
|
||||
|
||||
class BCryptPasswordHasher(BCryptSHA256PasswordHasher):
|
||||
"""
|
||||
|
|
|
@ -56,6 +56,9 @@ Minor features
|
|||
subclassed ``django.contrib.auth.hashers.PBKDF2PasswordHasher`` to change the
|
||||
default value.
|
||||
|
||||
* The ``BCryptSHA256PasswordHasher`` will now update passwords if its
|
||||
``rounds`` attribute is changed.
|
||||
|
||||
:mod:`django.contrib.gis`
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -177,6 +177,38 @@ class TestUtilsHashPass(SimpleTestCase):
|
|||
self.assertTrue(check_password('', blank_encoded))
|
||||
self.assertFalse(check_password(' ', blank_encoded))
|
||||
|
||||
@skipUnless(bcrypt, "bcrypt not installed")
|
||||
def test_bcrypt_upgrade(self):
|
||||
hasher = get_hasher('bcrypt')
|
||||
self.assertEqual('bcrypt', hasher.algorithm)
|
||||
self.assertNotEqual(hasher.rounds, 4)
|
||||
|
||||
old_rounds = hasher.rounds
|
||||
try:
|
||||
# Generate a password with 4 rounds.
|
||||
hasher.rounds = 4
|
||||
encoded = make_password('letmein', hasher='bcrypt')
|
||||
rounds = hasher.safe_summary(encoded)['work factor']
|
||||
self.assertEqual(rounds, '04')
|
||||
|
||||
state = {'upgraded': False}
|
||||
|
||||
def setter(password):
|
||||
state['upgraded'] = True
|
||||
|
||||
# Check that no upgrade is triggered.
|
||||
self.assertTrue(check_password('letmein', encoded, setter, 'bcrypt'))
|
||||
self.assertFalse(state['upgraded'])
|
||||
|
||||
# Revert to the old rounds count and ...
|
||||
hasher.rounds = old_rounds
|
||||
|
||||
# ... check if the password would get updated to the new count.
|
||||
self.assertTrue(check_password('letmein', encoded, setter, 'bcrypt'))
|
||||
self.assertTrue(state['upgraded'])
|
||||
finally:
|
||||
hasher.rounds = old_rounds
|
||||
|
||||
def test_unusable(self):
|
||||
encoded = make_password(None)
|
||||
self.assertEqual(len(encoded), len(UNUSABLE_PASSWORD_PREFIX) + UNUSABLE_PASSWORD_SUFFIX_LENGTH)
|
||||
|
|
Loading…
Reference in New Issue