21
23
class TestUtilsHashPass(unittest.TestCase):
23
26
load_hashers(password_hashers=default_hashers)
25
28
def test_simple(self):
26
encoded = make_password('letmein')
29
encoded = make_password('lètmein')
27
30
self.assertTrue(encoded.startswith('pbkdf2_sha256$'))
28
31
self.assertTrue(is_password_usable(encoded))
29
self.assertTrue(check_password(u'letmein', encoded))
30
self.assertFalse(check_password('letmeinz', encoded))
32
self.assertTrue(check_password('lètmein', encoded))
33
self.assertFalse(check_password('lètmeinz', encoded))
32
35
def test_pkbdf2(self):
33
encoded = make_password('letmein', 'seasalt', 'pbkdf2_sha256')
34
self.assertEqual(encoded,
35
'pbkdf2_sha256$10000$seasalt$FQCNpiZpTb0zub+HBsH6TOwyRxJ19FwvjbweatNmK/Y=')
36
encoded = make_password('lètmein', 'seasalt', 'pbkdf2_sha256')
37
self.assertEqual(encoded,
38
'pbkdf2_sha256$10000$seasalt$CWWFdHOWwPnki7HvkcqN9iA2T3KLW1cf2uZ5kvArtVY=')
36
39
self.assertTrue(is_password_usable(encoded))
37
self.assertTrue(check_password(u'letmein', encoded))
38
self.assertFalse(check_password('letmeinz', encoded))
40
self.assertTrue(check_password('lètmein', encoded))
41
self.assertFalse(check_password('lètmeinz', encoded))
42
self.assertEqual(identify_hasher(encoded).algorithm, "pbkdf2_sha256")
40
44
def test_sha1(self):
41
encoded = make_password('letmein', 'seasalt', 'sha1')
42
self.assertEqual(encoded,
43
'sha1$seasalt$fec3530984afba6bade3347b7140d1a7da7da8c7')
45
encoded = make_password('lètmein', 'seasalt', 'sha1')
46
self.assertEqual(encoded,
47
'sha1$seasalt$cff36ea83f5706ce9aa7454e63e431fc726b2dc8')
44
48
self.assertTrue(is_password_usable(encoded))
45
self.assertTrue(check_password(u'letmein', encoded))
46
self.assertFalse(check_password('letmeinz', encoded))
49
self.assertTrue(check_password('lètmein', encoded))
50
self.assertFalse(check_password('lètmeinz', encoded))
51
self.assertEqual(identify_hasher(encoded).algorithm, "sha1")
48
53
def test_md5(self):
49
encoded = make_password('letmein', 'seasalt', 'md5')
50
self.assertEqual(encoded,
51
'md5$seasalt$f5531bef9f3687d0ccf0f617f0e25573')
54
encoded = make_password('lètmein', 'seasalt', 'md5')
55
self.assertEqual(encoded,
56
'md5$seasalt$3f86d0d3d465b7b458c231bf3555c0e3')
52
57
self.assertTrue(is_password_usable(encoded))
53
self.assertTrue(check_password(u'letmein', encoded))
54
self.assertFalse(check_password('letmeinz', encoded))
58
self.assertTrue(check_password('lètmein', encoded))
59
self.assertFalse(check_password('lètmeinz', encoded))
60
self.assertEqual(identify_hasher(encoded).algorithm, "md5")
56
62
def test_unsalted_md5(self):
57
encoded = make_password('letmein', 'seasalt', 'unsalted_md5')
58
self.assertEqual(encoded, '0d107d09f5bbe40cade3de5c71e9e9b7')
63
encoded = make_password('lètmein', '', 'unsalted_md5')
64
self.assertEqual(encoded, '88a434c88cca4e900f7874cd98123f43')
59
65
self.assertTrue(is_password_usable(encoded))
60
self.assertTrue(check_password(u'letmein', encoded))
61
self.assertFalse(check_password('letmeinz', encoded))
66
self.assertTrue(check_password('lètmein', encoded))
67
self.assertFalse(check_password('lètmeinz', encoded))
68
self.assertEqual(identify_hasher(encoded).algorithm, "unsalted_md5")
62
69
# Alternate unsalted syntax
63
70
alt_encoded = "md5$$%s" % encoded
64
71
self.assertTrue(is_password_usable(alt_encoded))
65
self.assertTrue(check_password(u'letmein', alt_encoded))
66
self.assertFalse(check_password('letmeinz', alt_encoded))
72
self.assertTrue(check_password('lètmein', alt_encoded))
73
self.assertFalse(check_password('lètmeinz', alt_encoded))
75
def test_unsalted_sha1(self):
76
encoded = make_password('lètmein', '', 'unsalted_sha1')
77
self.assertEqual(encoded, 'sha1$$6d138ca3ae545631b3abd71a4f076ce759c5700b')
78
self.assertTrue(is_password_usable(encoded))
79
self.assertTrue(check_password('lètmein', encoded))
80
self.assertFalse(check_password('lètmeinz', encoded))
81
self.assertEqual(identify_hasher(encoded).algorithm, "unsalted_sha1")
82
# Raw SHA1 isn't acceptable
83
alt_encoded = encoded[6:]
84
self.assertFalse(check_password('lètmein', alt_encoded))
68
86
@skipUnless(crypt, "no crypt module to generate password.")
69
87
def test_crypt(self):
70
encoded = make_password('letmein', 'ab', 'crypt')
71
self.assertEqual(encoded, 'crypt$$abN/qM.L/H8EQ')
88
encoded = make_password('lètmei', 'ab', 'crypt')
89
self.assertEqual(encoded, 'crypt$$ab1Hv2Lg7ltQo')
72
90
self.assertTrue(is_password_usable(encoded))
73
self.assertTrue(check_password(u'letmein', encoded))
74
self.assertFalse(check_password('letmeinz', encoded))
91
self.assertTrue(check_password('lètmei', encoded))
92
self.assertFalse(check_password('lètmeiz', encoded))
93
self.assertEqual(identify_hasher(encoded).algorithm, "crypt")
76
95
@skipUnless(bcrypt, "py-bcrypt not installed")
77
96
def test_bcrypt(self):
78
encoded = make_password('letmein', hasher='bcrypt')
97
encoded = make_password('lètmein', hasher='bcrypt')
79
98
self.assertTrue(is_password_usable(encoded))
80
99
self.assertTrue(encoded.startswith('bcrypt$'))
81
self.assertTrue(check_password(u'letmein', encoded))
82
self.assertFalse(check_password('letmeinz', encoded))
100
self.assertTrue(check_password('lètmein', encoded))
101
self.assertFalse(check_password('lètmeinz', encoded))
102
self.assertEqual(identify_hasher(encoded).algorithm, "bcrypt")
84
104
def test_unusable(self):
85
105
encoded = make_password(None)
87
107
self.assertFalse(check_password(None, encoded))
88
108
self.assertFalse(check_password(UNUSABLE_PASSWORD, encoded))
89
109
self.assertFalse(check_password('', encoded))
90
self.assertFalse(check_password(u'letmein', encoded))
91
self.assertFalse(check_password('letmeinz', encoded))
110
self.assertFalse(check_password('lètmein', encoded))
111
self.assertFalse(check_password('lètmeinz', encoded))
112
self.assertRaises(ValueError, identify_hasher, encoded)
93
114
def test_bad_algorithm(self):
95
make_password('letmein', hasher='lolcat')
116
make_password('lètmein', hasher='lolcat')
96
117
self.assertRaises(ValueError, doit)
118
self.assertRaises(ValueError, identify_hasher, "lolcat$salt$hash")
120
def test_bad_encoded(self):
121
self.assertFalse(is_password_usable('lètmein_badencoded'))
122
self.assertFalse(is_password_usable(''))
98
124
def test_low_level_pkbdf2(self):
99
125
hasher = PBKDF2PasswordHasher()
100
encoded = hasher.encode('letmein', 'seasalt')
101
self.assertEqual(encoded,
102
'pbkdf2_sha256$10000$seasalt$FQCNpiZpTb0zub+HBsH6TOwyRxJ19FwvjbweatNmK/Y=')
103
self.assertTrue(hasher.verify('letmein', encoded))
126
encoded = hasher.encode('lètmein', 'seasalt')
127
self.assertEqual(encoded,
128
'pbkdf2_sha256$10000$seasalt$CWWFdHOWwPnki7HvkcqN9iA2T3KLW1cf2uZ5kvArtVY=')
129
self.assertTrue(hasher.verify('lètmein', encoded))
105
131
def test_low_level_pbkdf2_sha1(self):
106
132
hasher = PBKDF2SHA1PasswordHasher()
107
encoded = hasher.encode('letmein', 'seasalt')
108
self.assertEqual(encoded,
109
'pbkdf2_sha1$10000$seasalt$91JiNKgwADC8j2j86Ije/cc4vfQ=')
110
self.assertTrue(hasher.verify('letmein', encoded))
133
encoded = hasher.encode('lètmein', 'seasalt')
134
self.assertEqual(encoded,
135
'pbkdf2_sha1$10000$seasalt$oAfF6vgs95ncksAhGXOWf4Okq7o=')
136
self.assertTrue(hasher.verify('lètmein', encoded))
112
138
def test_upgrade(self):
113
139
self.assertEqual('pbkdf2_sha256', get_hasher('default').algorithm)
114
140
for algo in ('sha1', 'md5'):
115
encoded = make_password('letmein', hasher=algo)
141
encoded = make_password('lètmein', hasher=algo)
116
142
state = {'upgraded': False}
117
143
def setter(password):
118
144
state['upgraded'] = True
119
self.assertTrue(check_password('letmein', encoded, setter))
145
self.assertTrue(check_password('lètmein', encoded, setter))
120
146
self.assertTrue(state['upgraded'])
122
148
def test_no_upgrade(self):
123
encoded = make_password('letmein')
149
encoded = make_password('lètmein')
124
150
state = {'upgraded': False}
126
152
state['upgraded'] = True