mirror of https://github.com/django/django.git
Fixed #21535 -- Fixed password hash iteration upgrade.
Thanks jared_mess for the report.
This commit is contained in:
parent
2688462f91
commit
fddb0131d3
|
@ -57,7 +57,7 @@ def check_password(password, encoded, setter=None, preferred='default'):
|
||||||
|
|
||||||
must_update = hasher.algorithm != preferred.algorithm
|
must_update = hasher.algorithm != preferred.algorithm
|
||||||
if not must_update:
|
if not must_update:
|
||||||
must_update = hasher.must_update(encoded)
|
must_update = preferred.must_update(encoded)
|
||||||
is_correct = hasher.verify(password, encoded)
|
is_correct = hasher.verify(password, encoded)
|
||||||
if setter and is_correct and must_update:
|
if setter and is_correct and must_update:
|
||||||
setter(password)
|
setter(password)
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import unittest
|
|
||||||
from unittest import skipUnless
|
from unittest import skipUnless
|
||||||
|
|
||||||
from django.conf.global_settings import PASSWORD_HASHERS as default_hashers
|
from django.conf.global_settings import PASSWORD_HASHERS as default_hashers
|
||||||
from django.contrib.auth.hashers import (is_password_usable, BasePasswordHasher,
|
from django.contrib.auth.hashers import (is_password_usable, BasePasswordHasher,
|
||||||
check_password, make_password, PBKDF2PasswordHasher, load_hashers, PBKDF2SHA1PasswordHasher,
|
check_password, make_password, PBKDF2PasswordHasher, load_hashers, PBKDF2SHA1PasswordHasher,
|
||||||
get_hasher, identify_hasher, UNUSABLE_PASSWORD_PREFIX, UNUSABLE_PASSWORD_SUFFIX_LENGTH)
|
get_hasher, identify_hasher, UNUSABLE_PASSWORD_PREFIX, UNUSABLE_PASSWORD_SUFFIX_LENGTH)
|
||||||
|
from django.test import SimpleTestCase
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,7 +22,11 @@ except ImportError:
|
||||||
bcrypt = None
|
bcrypt = None
|
||||||
|
|
||||||
|
|
||||||
class TestUtilsHashPass(unittest.TestCase):
|
class PBKDF2SingleIterationHasher(PBKDF2PasswordHasher):
|
||||||
|
iterations = 1
|
||||||
|
|
||||||
|
|
||||||
|
class TestUtilsHashPass(SimpleTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
load_hashers(password_hashers=default_hashers)
|
load_hashers(password_hashers=default_hashers)
|
||||||
|
@ -279,6 +283,34 @@ class TestUtilsHashPass(unittest.TestCase):
|
||||||
finally:
|
finally:
|
||||||
hasher.iterations = old_iterations
|
hasher.iterations = old_iterations
|
||||||
|
|
||||||
|
def test_pbkdf2_upgrade_new_hasher(self):
|
||||||
|
self.assertEqual('pbkdf2_sha256', get_hasher('default').algorithm)
|
||||||
|
hasher = get_hasher('default')
|
||||||
|
self.assertNotEqual(hasher.iterations, 1)
|
||||||
|
|
||||||
|
state = {'upgraded': False}
|
||||||
|
|
||||||
|
def setter(password):
|
||||||
|
state['upgraded'] = True
|
||||||
|
|
||||||
|
with self.settings(PASSWORD_HASHERS=[
|
||||||
|
'django.contrib.auth.tests.test_hashers.PBKDF2SingleIterationHasher']):
|
||||||
|
encoded = make_password('letmein')
|
||||||
|
algo, iterations, salt, hash = encoded.split('$', 3)
|
||||||
|
self.assertEqual(iterations, '1')
|
||||||
|
|
||||||
|
# Check that no upgrade is triggerd
|
||||||
|
self.assertTrue(check_password('letmein', encoded, setter))
|
||||||
|
self.assertFalse(state['upgraded'])
|
||||||
|
|
||||||
|
# Revert to the old iteration count and check if the password would get
|
||||||
|
# updated to the new iteration count.
|
||||||
|
with self.settings(PASSWORD_HASHERS=[
|
||||||
|
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
|
||||||
|
'django.contrib.auth.tests.test_hashers.PBKDF2SingleIterationHasher']):
|
||||||
|
self.assertTrue(check_password('letmein', encoded, setter))
|
||||||
|
self.assertTrue(state['upgraded'])
|
||||||
|
|
||||||
def test_load_library_no_algorithm(self):
|
def test_load_library_no_algorithm(self):
|
||||||
with self.assertRaises(ValueError) as e:
|
with self.assertRaises(ValueError) as e:
|
||||||
BasePasswordHasher()._load_library()
|
BasePasswordHasher()._load_library()
|
||||||
|
|
|
@ -40,3 +40,4 @@ Bug fixes
|
||||||
* Fixed test client ``logout()`` method when using the cookie-based session
|
* Fixed test client ``logout()`` method when using the cookie-based session
|
||||||
backend (#21448).
|
backend (#21448).
|
||||||
* Fixed a crash when a ``GeometryField`` uses a non-geometric widget (#21496).
|
* Fixed a crash when a ``GeometryField`` uses a non-geometric widget (#21496).
|
||||||
|
* Fixed password hash upgrade when changing the iteration count (#21535).
|
||||||
|
|
Loading…
Reference in New Issue