@@ -155,11 +155,11 @@ def test_make_hash_constant_string(self):
155155 random seed. I.e. the value may differ across interpreter invocations
156156 but remains constant in same interpreter.
157157 """
158- first = make_hash (
159- DUMMY_WEAK_PW , _urandom = lambda vlen : DUMMY_SALT [:vlen ])
160- second = make_hash (
161- DUMMY_WEAK_PW , _urandom = lambda vlen : DUMMY_SALT [:vlen ])
162- self .assertEqual (first , second , "hashing is not constant" )
158+ first = make_hash (DUMMY_WEAK_PW ,
159+ _urandom = lambda vlen : DUMMY_SALT [:vlen ])
160+ second = make_hash (DUMMY_WEAK_PW ,
161+ _urandom = lambda vlen : DUMMY_SALT [:vlen ])
162+ self .assertEqual (first , second , "same seed hashing is not constant" )
163163
164164 def test_check_hash_reject_weak (self ):
165165 """Test basic hash checking of a constant weak complexity password"""
@@ -209,8 +209,8 @@ def test_check_hash_accept_modern(self):
209209 allow_legacy = False )
210210 self .assertTrue (result , "check hash must accept modern complexity pw" )
211211
212- def test_check_hash_constant (self ):
213- """Test basic hash checking of a constant string"""
212+ def test_check_hash_fixed (self ):
213+ """Test basic hash checking of a fixed string"""
214214 expected = make_hash (DUMMY_MEDIUM_PW )
215215 result = check_hash (self .dummy_conf , DUMMY_SERVICE , DUMMY_USER ,
216216 DUMMY_MEDIUM_PW , expected , strict_policy = True )
@@ -232,6 +232,33 @@ def test_check_hash_random(self):
232232 random_pw , expected )
233233 self .assertTrue (result , "mismatch in random hash check" )
234234
235+ def test_make_hash_variation (self ):
236+ """Test how hashing of a fixed string varies depending on random seed.
237+ I.e. the value likely remains constant in same interpreter but differs
238+ across interpreter invocations.
239+ """
240+ first = make_hash (DUMMY_MODERN_PW ,
241+ _urandom = lambda vlen : DUMMY_SALT [:vlen ])
242+ second = make_hash (DUMMY_MODERN_PW ,
243+ _urandom = lambda vlen : DUMMY_SALT [::- 1 ][:vlen ])
244+ self .assertNotEqual (first , second , "varying seed hashing is constant" )
245+
246+ def test_check_hash_despite_variation (self ):
247+ """Test that check_hash works independently of random seed variation.
248+ I.e. the hash value differs across interpreter invocations but testing
249+ the same password against each succeeds.
250+ """
251+ first = make_hash (DUMMY_MODERN_PW ,
252+ _urandom = lambda vlen : DUMMY_SALT [:vlen ])
253+ second = make_hash (DUMMY_MODERN_PW ,
254+ _urandom = lambda vlen : DUMMY_SALT [::- 1 ][:vlen ])
255+ result = check_hash (self .dummy_conf , DUMMY_SERVICE , DUMMY_USER ,
256+ DUMMY_MODERN_PW , first )
257+ self .assertTrue (result , "mismatch in 1st random password hash check" )
258+ result = check_hash (self .dummy_conf , DUMMY_SERVICE , DUMMY_USER ,
259+ DUMMY_MODERN_PW , second )
260+ self .assertTrue (result , "mismatch in 2nd random password hash check" )
261+
235262 def test_check_digest (self ):
236263 """Test basic digest checking of a random string"""
237264 random_pw = generate_random_password (self .dummy_conf )
@@ -317,8 +344,8 @@ def test_check_encrypt(self):
317344 random_pw , encrypted , algo = 'aesgcm_static' )
318345 self .assertTrue (result , "mismatch in aesgcm_static encrypt check" )
319346
320- def test_password_reset_token (self ):
321- """Test basic password reset token handling on a random string """
347+ def test_password_reset_token_generate_and_verify (self ):
348+ """Test basic password reset token generate and verify helper """
322349 random_pw = generate_random_password (self .dummy_conf )
323350 hashed_pw = make_hash (random_pw )
324351 dummy_user = {'distinguished_name' : DUMMY_USER }
@@ -333,6 +360,23 @@ def test_password_reset_token(self):
333360 DUMMY_SERVICE , timestamp )
334361 self .assertTrue (result , "failed password reset token handling" )
335362
363+ def test_password_reset_token_verify_expired (self ):
364+ """Test basic password reset token verify failure after it expired"""
365+ random_pw = generate_random_password (self .dummy_conf )
366+ hashed_pw = make_hash (random_pw )
367+ dummy_user = {'distinguished_name' : DUMMY_USER }
368+ dummy_user ['password_hash' ] = hashed_pw
369+ timestamp = 42
370+ expected = generate_reset_token (self .dummy_conf , dummy_user ,
371+ DUMMY_SERVICE , timestamp )
372+ parsed = parse_reset_token (self .dummy_conf , expected , DUMMY_SERVICE )
373+ self .assertEqual (parsed [0 ], timestamp , "failed parse token time" )
374+ self .assertEqual (parsed [1 ], hashed_pw , "failed parse token hash" )
375+ timestamp = 4242
376+ result = verify_reset_token (self .dummy_conf , dummy_user , expected ,
377+ DUMMY_SERVICE , timestamp )
378+ self .assertFalse (result , "failed password reset token expiry check" )
379+
336380 # TODO: migrate remaining inline checks from module here instead
337381
338382
0 commit comments