bpo-31702: Allow to specify rounds for SHA-2 hashing in crypt.mksalt(). (#4110)

The log_rounds parameter for Blowfish has been replaced with the rounds parameter.
This commit is contained in:
Serhiy Storchaka 2017-11-16 13:22:51 +02:00 committed by GitHub
parent ccb0442a33
commit cede8c9edb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 74 additions and 28 deletions

View file

@ -39,12 +39,26 @@ class CryptTestCase(unittest.TestCase):
else:
self.assertEqual(crypt.methods[-1], crypt.METHOD_CRYPT)
@unittest.skipUnless(crypt.METHOD_SHA256 in crypt.methods or
crypt.METHOD_SHA512 in crypt.methods,
'requires support of SHA-2')
def test_sha2_rounds(self):
for method in (crypt.METHOD_SHA256, crypt.METHOD_SHA512):
for rounds in 1000, 10_000, 100_000:
salt = crypt.mksalt(method, rounds=rounds)
self.assertIn('$rounds=%d$' % rounds, salt)
self.assertEqual(len(salt) - method.salt_chars,
11 + len(str(rounds)))
cr = crypt.crypt('mypassword', salt)
self.assertTrue(cr)
cr2 = crypt.crypt('mypassword', cr)
self.assertEqual(cr2, cr)
@unittest.skipUnless(crypt.METHOD_BLOWFISH in crypt.methods,
'requires support of Blowfish')
def test_log_rounds(self):
self.assertEqual(len(crypt._saltchars), 64)
def test_blowfish_rounds(self):
for log_rounds in range(4, 11):
salt = crypt.mksalt(crypt.METHOD_BLOWFISH, log_rounds=log_rounds)
salt = crypt.mksalt(crypt.METHOD_BLOWFISH, rounds=1 << log_rounds)
self.assertIn('$%02d$' % log_rounds, salt)
self.assertIn(len(salt) - crypt.METHOD_BLOWFISH.salt_chars, {6, 7})
cr = crypt.crypt('mypassword', salt)
@ -52,18 +66,21 @@ class CryptTestCase(unittest.TestCase):
cr2 = crypt.crypt('mypassword', cr)
self.assertEqual(cr2, cr)
@unittest.skipUnless(crypt.METHOD_BLOWFISH in crypt.methods,
'requires support of Blowfish')
def test_invalid_log_rounds(self):
for log_rounds in (1, -1, 999):
salt = crypt.mksalt(crypt.METHOD_BLOWFISH, log_rounds=log_rounds)
cr = crypt.crypt('mypassword', salt)
if cr is not None:
# On failure the openwall implementation returns a magic
# string that is shorter than 13 characters and is guaranteed
# to differ from a salt.
self.assertNotEqual(cr, salt)
self.assertLess(len(cr), 13)
def test_invalid_rounds(self):
for method in (crypt.METHOD_SHA256, crypt.METHOD_SHA512,
crypt.METHOD_BLOWFISH):
with self.assertRaises(TypeError):
crypt.mksalt(method, rounds='4096')
with self.assertRaises(TypeError):
crypt.mksalt(method, rounds=4096.0)
for rounds in (0, 1, -1, 1<<999):
with self.assertRaises(ValueError):
crypt.mksalt(method, rounds=rounds)
with self.assertRaises(ValueError):
crypt.mksalt(crypt.METHOD_BLOWFISH, rounds=1000)
for method in (crypt.METHOD_CRYPT, crypt.METHOD_MD5):
with self.assertRaisesRegex(ValueError, 'support'):
crypt.mksalt(method, rounds=4096)
if __name__ == "__main__":