Skip to content

Commit d9be6c2

Browse files
committed
Expand test coverage to fundamentally cover make+check functions for
simple hash, hash and digest. Mixes in various policy configurations.
1 parent 62ae485 commit d9be6c2

File tree

1 file changed

+143
-11
lines changed

1 file changed

+143
-11
lines changed

tests/test_mig_shared_pwcrypto.py

Lines changed: 143 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
"""Unit tests for the migrid module pointed to in the filename"""
2929

30+
import base64
3031
import os
3132
import sys
3233

@@ -40,12 +41,18 @@
4041

4142
DUMMY_USER = "dummy-user"
4243
DUMMY_ID = "dummy-id"
43-
DUMMY_PW = 'foobar'
44-
DUMMY_PW_HASH = \
44+
DUMMY_WEAK_PW = 'foobar'
45+
DUMMY_MEDIUM_PW = 'QZFnCp7h'
46+
DUMMY_HIGH_PW = 'QZFnp7I-GZ'
47+
DUMMY_MODERN_PW = 'QZFnCp7hmI1G'
48+
DUMMY_WEAK_PW_MD5 = "3858f62230ac3c915f300c664312c63f"
49+
DUMMY_WEAK_PW_PBKDF2 = \
4550
"PBKDF2$sha256$10000$MDAwMDAwMDAwMDAw$epib2rEg/HYTQZFnCp7hmIGZ6rzHnViy"
4651
DUMMY_HOME_DIR = 'dummy_user_home'
4752
DUMMY_SETTINGS_DIR = 'dummy_user_settings'
48-
DUMMY_SERVICE = 'svc'
53+
DUMMY_SERVICE = 'dummy-svc'
54+
DUMMY_REALM = 'dummy-realm'
55+
DUMMY_SALT = base64.b16encode(os.urandom(16))
4956

5057

5158
class MigSharedPwCrypto(MigTestCase):
@@ -61,26 +68,151 @@ def before_each(self):
6168
# now create a configuration
6269
self.dummy_conf = FakeConfiguration(
6370
user_home=test_user_home, user_settings=test_user_settings,
64-
site_password_policy=POLICY_HIGH,
71+
site_password_policy="%s:12" % POLICY_MODERN,
6572
site_password_legacy_policy=POLICY_MEDIUM,
66-
site_password_cracklib=False)
73+
site_password_cracklib=False,
74+
site_crypto_salt=DUMMY_SALT,
75+
site_password_salt=DUMMY_SALT,
76+
site_digest_salt=DUMMY_SALT,
77+
)
6778

68-
def test_make_hash_constant_string(self):
79+
def test_best_crypt_salt(self):
80+
"""Test selection of best salt based on salt availability in
81+
configuration. Disable best choice in turn and check fallback.
82+
"""
83+
expected = DUMMY_SALT
84+
actual = best_crypt_salt(self.dummy_conf)
85+
self.assertEqual(actual, expected, "best crypt salt not found")
86+
self.dummy_conf.site_crypto_salt = ''
87+
actual = best_crypt_salt(self.dummy_conf)
88+
self.assertEqual(actual, expected, "2nd best crypt salt not found")
89+
self.dummy_conf.site_password_salt = ''
90+
actual = best_crypt_salt(self.dummy_conf)
91+
self.assertEqual(actual, expected, "3rd best crypt salt not found")
92+
self.dummy_conf.site_digest_salt = ''
93+
actual = None
94+
try:
95+
actual = best_crypt_salt(self.dummy_conf)
96+
except Exception as exc:
97+
pass
98+
self.assertTrue(actual is None, "best crypt salt failed to err")
99+
100+
def test_make_simple_hash_fixed_seed(self):
101+
"""Test basic hashing of a fixed string to be constant"""
102+
expected = DUMMY_WEAK_PW_MD5
103+
actual = make_simple_hash(DUMMY_WEAK_PW)
104+
self.assertEqual(actual, expected, "mismatch simple hash string")
105+
106+
def test_make_simple_hash_constant_string(self):
107+
"""Test basic hashing of a fixed string to be constant for a particular
108+
random seed. I.e. the value may differ across interpreter invocations
109+
but remains constant in same interpreter.
110+
"""
111+
first = make_simple_hash(DUMMY_WEAK_PW)
112+
second = make_simple_hash(DUMMY_WEAK_PW)
113+
self.assertEqual(first, second, "simple hashing is not constant")
114+
115+
def test_make_hash_fixed_seed(self):
69116
"""Test basic hashing of a fixed string to be constant for a fixed
70117
random seed.
71118
"""
72-
actual = make_hash(DUMMY_PW, _urandom=lambda vlen: b'0' * vlen)
73-
self.assertEqual(actual, DUMMY_PW_HASH, "mismatch hashing string")
119+
expected = DUMMY_WEAK_PW_PBKDF2
120+
actual = make_hash(DUMMY_WEAK_PW, _urandom=lambda vlen: b'0' * vlen)
121+
self.assertEqual(actual, expected, "mismatch hashing string")
122+
123+
def test_make_hash_constant_string(self):
124+
"""Test basic hashing of a fixed string to be constant for a particular
125+
random seed. I.e. the value may differ across interpreter invocations
126+
but remains constant in same interpreter.
127+
"""
128+
first = make_hash(
129+
DUMMY_WEAK_PW, _urandom=lambda vlen: DUMMY_SALT[:vlen])
130+
second = make_hash(
131+
DUMMY_WEAK_PW, _urandom=lambda vlen: DUMMY_SALT[:vlen])
132+
self.assertEqual(first, second, "hashing is not constant")
133+
134+
def test_check_hash_reject_weak(self):
135+
"""Test basic hash checking of a constant weak complexity password"""
136+
expected = make_hash(DUMMY_WEAK_PW)
137+
result = check_hash(self.dummy_conf, DUMMY_SERVICE, DUMMY_USER,
138+
DUMMY_WEAK_PW, expected, strict_policy=True)
139+
self.assertFalse(result, "check hash should fail on weak pw")
140+
141+
def test_check_hash_reject_medium_without_legacy(self):
142+
"""Test basic hash checking of a constant medium complexity password
143+
without legacy password support.
144+
"""
145+
expected = make_hash(DUMMY_MEDIUM_PW)
146+
result = check_hash(self.dummy_conf, DUMMY_SERVICE, DUMMY_USER,
147+
DUMMY_MEDIUM_PW, expected, strict_policy=True,
148+
allow_legacy=False)
149+
self.assertFalse(result, "check hash strict should fail on medium pw")
150+
151+
def test_check_hash_accept_medium_with_legacy(self):
152+
"""Test basic hash checking of a constant medium complexity password
153+
with legacy password support.
154+
"""
155+
expected = make_hash(DUMMY_MEDIUM_PW)
156+
result = check_hash(self.dummy_conf, DUMMY_SERVICE, DUMMY_USER,
157+
DUMMY_MEDIUM_PW, expected, strict_policy=True,
158+
allow_legacy=True)
159+
self.assertTrue(result, "check hash with legacy must accept medium pw")
160+
161+
def test_check_hash_accept_high(self):
162+
"""Test basic hash checking of a constant high complexity password
163+
without legacy password support.
164+
"""
165+
expected = make_hash(DUMMY_HIGH_PW)
166+
self.dummy_conf.site_password_policy = POLICY_HIGH
167+
result = check_hash(self.dummy_conf, DUMMY_SERVICE, DUMMY_USER,
168+
DUMMY_HIGH_PW, expected, strict_policy=True,
169+
allow_legacy=False)
170+
self.assertTrue(result, "check hash must accept high complexity pw")
171+
172+
def test_check_hash_accept_modern(self):
173+
"""Test basic hash checking of a constant modern complexity password
174+
without legacy password support.
175+
"""
176+
expected = make_hash(DUMMY_MODERN_PW)
177+
result = check_hash(self.dummy_conf, DUMMY_SERVICE, DUMMY_USER,
178+
DUMMY_MODERN_PW, expected, strict_policy=True,
179+
allow_legacy=False)
180+
self.assertTrue(result, "check hash must accept modern complexity pw")
74181

75-
def test_check_hash(self):
76-
"""Test basic hash checking of a fixed string"""
182+
def test_check_hash_constant(self):
183+
"""Test basic hash checking of a constant string"""
184+
expected = make_hash(DUMMY_MEDIUM_PW)
185+
result = check_hash(self.dummy_conf, DUMMY_SERVICE, DUMMY_USER,
186+
DUMMY_MEDIUM_PW, expected, strict_policy=True)
187+
self.assertFalse(result, "check hash should reject medium pw")
188+
result = check_hash(self.dummy_conf, DUMMY_SERVICE, DUMMY_USER,
189+
DUMMY_MEDIUM_PW, expected, strict_policy=False,
190+
allow_legacy=True)
191+
self.assertTrue(result, "check hash failed medium pw when not strict")
192+
expected = make_hash(DUMMY_MODERN_PW)
193+
result = check_hash(self.dummy_conf, DUMMY_SERVICE, DUMMY_USER,
194+
DUMMY_MODERN_PW, expected, strict_policy=True)
195+
self.assertTrue(result, "check hash failed modern pw")
77196

197+
def test_check_hash_random(self):
198+
"""Test basic hash checking of a random string"""
78199
random_pw = generate_random_password(self.dummy_conf)
79200
expected = make_hash(random_pw)
80201
result = check_hash(self.dummy_conf, DUMMY_SERVICE, DUMMY_USER,
81202
random_pw, expected)
203+
self.assertTrue(result, "mismatch in random hash check")
204+
205+
def test_check_digest(self):
206+
"""Test basic digest checking of a random string"""
207+
random_pw = generate_random_password(self.dummy_conf)
208+
expected = make_digest(DUMMY_REALM, DUMMY_USER,
209+
DUMMY_MODERN_PW, DUMMY_SALT)
210+
result = check_digest(self.dummy_conf, DUMMY_SERVICE, DUMMY_REALM,
211+
DUMMY_USER, DUMMY_MODERN_PW, expected,
212+
DUMMY_SALT)
213+
self.assertTrue(result, "mismatch in digest check")
82214

83-
self.assertTrue(result, "mismatch in hash check")
215+
# TODO: migrate inline checks from module here instead
84216

85217

86218
if __name__ == '__main__':

0 commit comments

Comments
 (0)