diff options
| author | Eli Collins <elic@assurancetechnologies.com> | 2011-10-07 21:39:00 -0400 |
|---|---|---|
| committer | Eli Collins <elic@assurancetechnologies.com> | 2011-10-07 21:39:00 -0400 |
| commit | aa5a479ebd92022691fe5ca933bedc2c81e7773c (patch) | |
| tree | 3f5236d9e90f3bdb65927a033d3a1c9256cb5f95 /passlib/tests | |
| parent | 88eff23353cf2f1b17971f1a97894e8c8e99a7d6 (diff) | |
| download | passlib-aa5a479ebd92022691fe5ca933bedc2c81e7773c.tar.gz | |
bcrypt padding work:
* added changelog entry re: issue & fix
* bcrypt now warns about padding bits in digest as well
* bcrypt.normhash() now normalizes salt padding bits, digest padding bits, and rounds zero-padding
* hash_needs_update() will now flag unclean bcrypt hashes as needing an update
* UTs for hash_needs_update(), and digest padding bit handling
Diffstat (limited to 'passlib/tests')
| -rw-r--r-- | passlib/tests/test_context.py | 25 | ||||
| -rw-r--r-- | passlib/tests/test_drivers.py | 21 |
2 files changed, 41 insertions, 5 deletions
diff --git a/passlib/tests/test_context.py b/passlib/tests/test_context.py index 10c7b9c..2d461d2 100644 --- a/passlib/tests/test_context.py +++ b/passlib/tests/test_context.py @@ -863,6 +863,31 @@ class CryptContextTest(TestCase): self.assertIs(new_hash, None) #========================================================= + # other + #========================================================= + def test_90_bcrypt_normhash(self): + "teset verify_and_update / hash_needs_update corrects bcrypt padding" + # see issue 25. + bcrypt = hash.bcrypt + + PASS1 = "loppux" + BAD1 = "$2a$12$oaQbBqq8JnSM1NHRPQGXORm4GCUMqp7meTnkft4zgSnrbhoKdDV0C" + GOOD1 = "$2a$12$oaQbBqq8JnSM1NHRPQGXOOm4GCUMqp7meTnkft4zgSnrbhoKdDV0C" + ctx = CryptContext(["bcrypt"]) + + with catch_warnings(record=True) as wlog: + warnings.simplefilter("always") + + self.assertTrue(ctx.hash_needs_update(BAD1)) + self.assertFalse(ctx.hash_needs_update(GOOD1)) + + if bcrypt.has_backend(): + self.assertEquals(ctx.verify_and_update(PASS1,GOOD1), (True,None)) + self.assertEquals(ctx.verify_and_update("x",BAD1), (False,None)) + res = ctx.verify_and_update(PASS1, BAD1) + self.assertTrue(res[0] and res[1] and res[1] != BAD1) + + #========================================================= #eoc #========================================================= diff --git a/passlib/tests/test_drivers.py b/passlib/tests/test_drivers.py index 5dcfbb7..526c9be 100644 --- a/passlib/tests/test_drivers.py +++ b/passlib/tests/test_drivers.py @@ -132,9 +132,9 @@ class _BCryptTest(HandlerCase): # correct provided salts to handle ending correctly, # so test_33_genconfig_saltchars doesn't throw warnings. if 'salt' in kwds: - from passlib.handlers.bcrypt import BCHARS, BCLAST + from passlib.handlers.bcrypt import BCHARS, BSLAST salt = kwds['salt'] - if salt and salt[-1] not in BCLAST: + if salt and salt[-1] not in BSLAST: salt = salt[:-1] + BCHARS[BCHARS.index(salt[-1])&~15] kwds['salt'] = salt return self.handler.genconfig(**kwds) @@ -152,13 +152,13 @@ class _BCryptTest(HandlerCase): def check_padding(hash): "check bcrypt hash doesn't have salt padding bits set" assert hash.startswith("$2a$") and len(hash) >= 28 - self.assertTrue(hash[28] in BCLAST, + self.assertTrue(hash[28] in BSLAST, "padding bits set in hash: %r" % (hash,)) #=============================================================== # test generated salts #=============================================================== - from passlib.handlers.bcrypt import BCHARS, BCLAST + from passlib.handlers.bcrypt import BCHARS, BSLAST # make sure genconfig & encrypt don't return bad hashes. # bug had 15/16 chance of occurring every time salt generated. @@ -184,14 +184,21 @@ class _BCryptTest(HandlerCase): # test handling existing hashes #=============================================================== + # 2 bits of salt padding set PASS1 = "loppux" BAD1 = "$2a$12$oaQbBqq8JnSM1NHRPQGXORm4GCUMqp7meTnkft4zgSnrbhoKdDV0C" GOOD1 = "$2a$12$oaQbBqq8JnSM1NHRPQGXOOm4GCUMqp7meTnkft4zgSnrbhoKdDV0C" + # all 4 bits of salt padding set PASS2 = "Passlib11" BAD2 = "$2a$12$M8mKpW9a2vZ7PYhq/8eJVcUtKxpo6j0zAezu0G/HAMYgMkhPu4fLK" GOOD2 = "$2a$12$M8mKpW9a2vZ7PYhq/8eJVOUtKxpo6j0zAezu0G/HAMYgMkhPu4fLK" + # bad checksum padding + PASS3 = "test" + BAD3 = "$2a$04$yjDgE74RJkeqC0/1NheSSOrvKeu9IbKDpcQf/Ox3qsrRS/Kw42qIV" + GOOD3 = "$2a$04$yjDgE74RJkeqC0/1NheSSOrvKeu9IbKDpcQf/Ox3qsrRS/Kw42qIS" + # make sure genhash() corrects input with catch_warnings(record=True) as wlog: warnings.simplefilter("always") @@ -204,7 +211,11 @@ class _BCryptTest(HandlerCase): self.assertEqual(bcrypt.genhash(PASS2, GOOD2), GOOD2) self.assertFalse(wlog) - + + self.assertEqual(bcrypt.genhash(PASS3, BAD3), GOOD3) + check_warning(wlog) + self.assertFalse(wlog) + # make sure verify works on both bad and good hashes with catch_warnings(record=True) as wlog: warnings.simplefilter("always") |
