mirror of
https://github.com/python/cpython.git
synced 2025-11-01 02:38:53 +00:00
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:
parent
ccb0442a33
commit
cede8c9edb
5 changed files with 74 additions and 28 deletions
|
|
@ -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__":
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue