diff --git a/django/contrib/auth/hashers.py b/django/contrib/auth/hashers.py
index 6abdb5f..a3e1511 100644
a
|
b
|
def check_password(password, encoded, setter=None, preferred='default'):
|
47 | 47 | If setter is specified, it'll be called when you need to |
48 | 48 | regenerate the password. |
49 | 49 | """ |
50 | | if not password or not is_password_usable(encoded): |
| 50 | if not is_password_usable(encoded): |
51 | 51 | return False |
52 | 52 | |
53 | 53 | preferred = get_hasher(preferred) |
… |
… |
def make_password(password, salt=None, hasher='default'):
|
68 | 68 | password is None or blank then UNUSABLE_PASSWORD will be |
69 | 69 | returned which disallows logins. |
70 | 70 | """ |
71 | | if not password: |
| 71 | if password is None: |
72 | 72 | return UNUSABLE_PASSWORD |
73 | 73 | |
74 | 74 | hasher = get_hasher(hasher) |
… |
… |
class PBKDF2PasswordHasher(BasePasswordHasher):
|
222 | 222 | digest = hashlib.sha256 |
223 | 223 | |
224 | 224 | def encode(self, password, salt, iterations=None): |
225 | | assert password |
226 | 225 | assert salt and '$' not in salt |
227 | 226 | if not iterations: |
228 | 227 | iterations = self.iterations |
… |
… |
class SHA1PasswordHasher(BasePasswordHasher):
|
350 | 349 | algorithm = "sha1" |
351 | 350 | |
352 | 351 | def encode(self, password, salt): |
353 | | assert password |
354 | 352 | assert salt and '$' not in salt |
355 | 353 | hash = hashlib.sha1(force_bytes(salt + password)).hexdigest() |
356 | 354 | return "%s$%s$%s" % (self.algorithm, salt, hash) |
… |
… |
class MD5PasswordHasher(BasePasswordHasher):
|
378 | 376 | algorithm = "md5" |
379 | 377 | |
380 | 378 | def encode(self, password, salt): |
381 | | assert password |
382 | 379 | assert salt and '$' not in salt |
383 | 380 | hash = hashlib.md5(force_bytes(salt + password)).hexdigest() |
384 | 381 | return "%s$%s$%s" % (self.algorithm, salt, hash) |
diff --git a/django/contrib/auth/tests/test_hashers.py b/django/contrib/auth/tests/test_hashers.py
index d49fdc4..88c8f40 100644
a
|
b
|
class TestUtilsHashPass(unittest.TestCase):
|
41 | 41 | self.assertFalse(check_password('lètmeinz', encoded)) |
42 | 42 | self.assertEqual(identify_hasher(encoded).algorithm, "pbkdf2_sha256") |
43 | 43 | |
| 44 | encoded = make_password('', 'sodium chloride', 'pbkdf2_sha256') |
| 45 | self.assertTrue(is_password_usable(encoded)) |
| 46 | self.assertTrue(check_password('', encoded)) |
| 47 | |
44 | 48 | def test_sha1(self): |
45 | 49 | encoded = make_password('lètmein', 'seasalt', 'sha1') |
46 | 50 | self.assertEqual(encoded, |
… |
… |
class TestUtilsHashPass(unittest.TestCase):
|
50 | 54 | self.assertFalse(check_password('lètmeinz', encoded)) |
51 | 55 | self.assertEqual(identify_hasher(encoded).algorithm, "sha1") |
52 | 56 | |
| 57 | encoded = make_password('', 'sodium chloride', 'sha1') |
| 58 | self.assertTrue(is_password_usable(encoded)) |
| 59 | self.assertTrue(check_password('', encoded)) |
| 60 | |
53 | 61 | def test_md5(self): |
54 | 62 | encoded = make_password('lètmein', 'seasalt', 'md5') |
55 | 63 | self.assertEqual(encoded, |
… |
… |
class TestUtilsHashPass(unittest.TestCase):
|
59 | 67 | self.assertFalse(check_password('lètmeinz', encoded)) |
60 | 68 | self.assertEqual(identify_hasher(encoded).algorithm, "md5") |
61 | 69 | |
| 70 | encoded = make_password('', 'sodium chloride', 'md5') |
| 71 | self.assertTrue(is_password_usable(encoded)) |
| 72 | self.assertTrue(check_password('', encoded)) |
| 73 | |
62 | 74 | def test_unsalted_md5(self): |
63 | 75 | encoded = make_password('lètmein', '', 'unsalted_md5') |
64 | 76 | self.assertEqual(encoded, '88a434c88cca4e900f7874cd98123f43') |
… |
… |
class TestUtilsHashPass(unittest.TestCase):
|
72 | 84 | self.assertTrue(check_password('lètmein', alt_encoded)) |
73 | 85 | self.assertFalse(check_password('lètmeinz', alt_encoded)) |
74 | 86 | |
| 87 | encoded = make_password('', '', 'unsalted_md5') |
| 88 | self.assertTrue(is_password_usable(encoded)) |
| 89 | self.assertTrue(check_password('', encoded)) |
| 90 | |
75 | 91 | def test_unsalted_sha1(self): |
76 | 92 | encoded = make_password('lètmein', '', 'unsalted_sha1') |
77 | 93 | self.assertEqual(encoded, 'sha1$$6d138ca3ae545631b3abd71a4f076ce759c5700b') |
… |
… |
class TestUtilsHashPass(unittest.TestCase):
|
83 | 99 | alt_encoded = encoded[6:] |
84 | 100 | self.assertFalse(check_password('lètmein', alt_encoded)) |
85 | 101 | |
| 102 | encoded = make_password('', '', 'unsalted_sha1') |
| 103 | self.assertTrue(is_password_usable(encoded)) |
| 104 | self.assertTrue(check_password('', encoded)) |
| 105 | |
86 | 106 | @skipUnless(crypt, "no crypt module to generate password.") |
87 | 107 | def test_crypt(self): |
88 | 108 | encoded = make_password('lètmei', 'ab', 'crypt') |
… |
… |
class TestUtilsHashPass(unittest.TestCase):
|
92 | 112 | self.assertFalse(check_password('lètmeiz', encoded)) |
93 | 113 | self.assertEqual(identify_hasher(encoded).algorithm, "crypt") |
94 | 114 | |
| 115 | encoded = make_password('', 'ab', 'crypt') |
| 116 | self.assertTrue(is_password_usable(encoded)) |
| 117 | self.assertTrue(check_password('', encoded)) |
| 118 | |
95 | 119 | @skipUnless(bcrypt, "bcrypt not installed") |
96 | 120 | def test_bcrypt_sha256(self): |
97 | 121 | encoded = make_password('lètmein', hasher='bcrypt_sha256') |
… |
… |
class TestUtilsHashPass(unittest.TestCase):
|
108 | 132 | self.assertTrue(check_password(password, encoded)) |
109 | 133 | self.assertFalse(check_password(password[:72], encoded)) |
110 | 134 | |
| 135 | encoded = make_password('', 'bcrypt_sha256') |
| 136 | self.assertTrue(is_password_usable(encoded)) |
| 137 | self.assertTrue(check_password('', encoded)) |
| 138 | |
111 | 139 | @skipUnless(bcrypt, "bcrypt not installed") |
112 | 140 | def test_bcrypt(self): |
113 | 141 | encoded = make_password('lètmein', hasher='bcrypt') |
… |
… |
class TestUtilsHashPass(unittest.TestCase):
|
117 | 145 | self.assertFalse(check_password('lètmeinz', encoded)) |
118 | 146 | self.assertEqual(identify_hasher(encoded).algorithm, "bcrypt") |
119 | 147 | |
| 148 | encoded = make_password('', 'bcrypt') |
| 149 | self.assertTrue(is_password_usable(encoded)) |
| 150 | self.assertTrue(check_password('', encoded)) |
| 151 | |
120 | 152 | def test_unusable(self): |
121 | 153 | encoded = make_password(None) |
122 | 154 | self.assertFalse(is_password_usable(encoded)) |
… |
… |
class TestUtilsHashPass(unittest.TestCase):
|
151 | 183 | 'pbkdf2_sha1$10000$seasalt$oAfF6vgs95ncksAhGXOWf4Okq7o=') |
152 | 184 | self.assertTrue(hasher.verify('lètmein', encoded)) |
153 | 185 | |
| 186 | encoded = hasher.encode('', 'sodium chloride') |
| 187 | self.assertTrue(hasher.verify('', encoded)) |
| 188 | |
154 | 189 | def test_upgrade(self): |
155 | 190 | self.assertEqual('pbkdf2_sha256', get_hasher('default').algorithm) |
156 | 191 | for algo in ('sha1', 'md5'): |