Ticket #18184: identify_hasher.patch
File identify_hasher.patch, 5.7 KB (added by , 13 years ago) |
---|
-
django/contrib/auth/hashers.py
116 116 return HASHERS[algorithm] 117 117 118 118 119 def identify_hasher(encoded): 120 """ 121 Returns an instance of a loaded password hasher. 122 123 Identifies hasher algorithm by examining encoded hash, and calls 124 get_hasher() to return hasher. Raises ValueError if 125 algorithm cannot be identified, or if hasher is not loaded. 126 """ 127 encoded = smart_str(encoded) 128 if len(encoded) == 32 and '$' not in encoded: 129 algorithm = 'unsalted_md5' 130 else: 131 algorithm = encoded.split('$', 1)[0] 132 return get_hasher(algorithm) 133 134 119 135 def mask_hash(hash, show=6, char="*"): 120 136 """ 121 137 Returns the given hash, with only the first ``show`` number shown. The -
django/contrib/auth/tests/hashers.py
1 1 from django.conf.global_settings import PASSWORD_HASHERS as default_hashers 2 2 from django.contrib.auth.hashers import (is_password_usable, 3 3 check_password, make_password, PBKDF2PasswordHasher, load_hashers, 4 PBKDF2SHA1PasswordHasher, get_hasher, UNUSABLE_PASSWORD)4 PBKDF2SHA1PasswordHasher, get_hasher, identify_hasher, UNUSABLE_PASSWORD) 5 5 from django.utils import unittest 6 6 from django.utils.unittest import skipUnless 7 7 … … 36 36 self.assertTrue(is_password_usable(encoded)) 37 37 self.assertTrue(check_password(u'letmein', encoded)) 38 38 self.assertFalse(check_password('letmeinz', encoded)) 39 self.assertEqual(identify_hasher(encoded).algorithm, "pbkdf2_sha256") 39 40 40 41 def test_sha1(self): 41 42 encoded = make_password('letmein', 'seasalt', 'sha1') … … 44 45 self.assertTrue(is_password_usable(encoded)) 45 46 self.assertTrue(check_password(u'letmein', encoded)) 46 47 self.assertFalse(check_password('letmeinz', encoded)) 48 self.assertEqual(identify_hasher(encoded).algorithm, "sha1") 47 49 48 50 def test_md5(self): 49 51 encoded = make_password('letmein', 'seasalt', 'md5') … … 52 54 self.assertTrue(is_password_usable(encoded)) 53 55 self.assertTrue(check_password(u'letmein', encoded)) 54 56 self.assertFalse(check_password('letmeinz', encoded)) 57 self.assertEqual(identify_hasher(encoded).algorithm, "md5") 55 58 56 59 def test_unsalted_md5(self): 57 60 encoded = make_password('letmein', 'seasalt', 'unsalted_md5') … … 59 62 self.assertTrue(is_password_usable(encoded)) 60 63 self.assertTrue(check_password(u'letmein', encoded)) 61 64 self.assertFalse(check_password('letmeinz', encoded)) 65 self.assertEqual(identify_hasher(encoded).algorithm, "unsalted_md5") 62 66 63 67 @skipUnless(crypt, "no crypt module to generate password.") 64 68 def test_crypt(self): … … 67 71 self.assertTrue(is_password_usable(encoded)) 68 72 self.assertTrue(check_password(u'letmein', encoded)) 69 73 self.assertFalse(check_password('letmeinz', encoded)) 74 self.assertEqual(identify_hasher(encoded).algorithm, "crypt") 70 75 71 76 @skipUnless(bcrypt, "py-bcrypt not installed") 72 77 def test_bcrypt(self): … … 75 80 self.assertTrue(encoded.startswith('bcrypt$')) 76 81 self.assertTrue(check_password(u'letmein', encoded)) 77 82 self.assertFalse(check_password('letmeinz', encoded)) 83 self.assertEqual(identify_hasher(encoded).algorithm, "bcrypt") 78 84 79 85 def test_unusable(self): 80 86 encoded = make_password(None) … … 84 90 self.assertFalse(check_password('', encoded)) 85 91 self.assertFalse(check_password(u'letmein', encoded)) 86 92 self.assertFalse(check_password('letmeinz', encoded)) 93 self.assertRaises(ValueError, identify_hasher, encoded) 87 94 88 95 def test_bad_algorithm(self): 89 96 def doit(): 90 97 make_password('letmein', hasher='lolcat') 91 98 self.assertRaises(ValueError, doit) 99 self.assertRaises(ValueError, identify_hasher, "lolcat$salt$hash") 92 100 93 101 def test_low_level_pkbdf2(self): 94 102 hasher = PBKDF2PasswordHasher() -
django/contrib/auth/forms.py
8 8 9 9 from django.contrib.auth import authenticate 10 10 from django.contrib.auth.models import User 11 from django.contrib.auth.hashers import UNUSABLE_PASSWORD, is_password_usable, get_hasher11 from django.contrib.auth.hashers import UNUSABLE_PASSWORD, is_password_usable, identify_hasher 12 12 from django.contrib.auth.tokens import default_token_generator 13 13 from django.contrib.sites.models import get_current_site 14 14 … … 26 26 27 27 final_attrs = self.build_attrs(attrs) 28 28 29 encoded = smart_str(encoded)30 31 if len(encoded) == 32 and '$' not in encoded:32 algorithm = 'unsalted_md5'33 else:34 algorithm = encoded.split('$', 1)[0]35 36 29 try: 37 hasher = get_hasher(algorithm)30 hasher = identify_hasher(encoded) 38 31 except ValueError: 39 32 summary = "<strong>Invalid password format or unknown hashing algorithm.</strong>" 40 33 else: 41 34 summary = "" 42 for key, value in hasher.safe_summary( encoded).iteritems():35 for key, value in hasher.safe_summary(smart_str(encoded)).iteritems(): 43 36 summary += "<strong>%(key)s</strong>: %(value)s " % {"key": ugettext(key), "value": value} 44 37 45 38 return mark_safe("<div%(attrs)s>%(summary)s</div>" % {"attrs": flatatt(final_attrs), "summary": summary})