mirror of
https://github.com/django/django.git
synced 2025-01-08 17:37:20 +00:00
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)),
|
(_('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):
|
class BCryptPasswordHasher(BCryptSHA256PasswordHasher):
|
||||||
"""
|
"""
|
||||||
|
@ -56,6 +56,9 @@ Minor features
|
|||||||
subclassed ``django.contrib.auth.hashers.PBKDF2PasswordHasher`` to change the
|
subclassed ``django.contrib.auth.hashers.PBKDF2PasswordHasher`` to change the
|
||||||
default value.
|
default value.
|
||||||
|
|
||||||
|
* The ``BCryptSHA256PasswordHasher`` will now update passwords if its
|
||||||
|
``rounds`` attribute is changed.
|
||||||
|
|
||||||
:mod:`django.contrib.gis`
|
:mod:`django.contrib.gis`
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
@ -177,6 +177,38 @@ class TestUtilsHashPass(SimpleTestCase):
|
|||||||
self.assertTrue(check_password('', blank_encoded))
|
self.assertTrue(check_password('', blank_encoded))
|
||||||
self.assertFalse(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):
|
def test_unusable(self):
|
||||||
encoded = make_password(None)
|
encoded = make_password(None)
|
||||||
self.assertEqual(len(encoded), len(UNUSABLE_PASSWORD_PREFIX) + UNUSABLE_PASSWORD_SUFFIX_LENGTH)
|
self.assertEqual(len(encoded), len(UNUSABLE_PASSWORD_PREFIX) + UNUSABLE_PASSWORD_SUFFIX_LENGTH)
|
||||||
|
Loading…
Reference in New Issue
Block a user