test_crypt.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import sys
  2. import unittest
  3. from test.support import check_sanitizer, warnings_helper
  4. try:
  5. if check_sanitizer(address=True, memory=True):
  6. raise unittest.SkipTest("The crypt module SEGFAULTs on ASAN/MSAN builds")
  7. crypt = warnings_helper.import_deprecated("crypt")
  8. IMPORT_ERROR = None
  9. except ImportError as ex:
  10. if sys.platform != 'win32':
  11. raise unittest.SkipTest(str(ex))
  12. crypt = None
  13. IMPORT_ERROR = str(ex)
  14. @unittest.skipUnless(sys.platform == 'win32', 'This should only run on windows')
  15. @unittest.skipIf(crypt, 'import succeeded')
  16. class TestWhyCryptDidNotImport(unittest.TestCase):
  17. def test_import_failure_message(self):
  18. self.assertIn('not supported', IMPORT_ERROR)
  19. @unittest.skipUnless(crypt, 'crypt module is required')
  20. class CryptTestCase(unittest.TestCase):
  21. def test_crypt(self):
  22. cr = crypt.crypt('mypassword')
  23. cr2 = crypt.crypt('mypassword', cr)
  24. self.assertEqual(cr2, cr)
  25. cr = crypt.crypt('mypassword', 'ab')
  26. if cr is not None:
  27. cr2 = crypt.crypt('mypassword', cr)
  28. self.assertEqual(cr2, cr)
  29. def test_salt(self):
  30. self.assertEqual(len(crypt._saltchars), 64)
  31. for method in crypt.methods:
  32. salt = crypt.mksalt(method)
  33. self.assertIn(len(salt) - method.salt_chars, {0, 1, 3, 4, 6, 7})
  34. if method.ident:
  35. self.assertIn(method.ident, salt[:len(salt)-method.salt_chars])
  36. def test_saltedcrypt(self):
  37. for method in crypt.methods:
  38. cr = crypt.crypt('assword', method)
  39. self.assertEqual(len(cr), method.total_size)
  40. cr2 = crypt.crypt('assword', cr)
  41. self.assertEqual(cr2, cr)
  42. cr = crypt.crypt('assword', crypt.mksalt(method))
  43. self.assertEqual(len(cr), method.total_size)
  44. def test_methods(self):
  45. self.assertTrue(len(crypt.methods) >= 1)
  46. if sys.platform.startswith('openbsd'):
  47. self.assertEqual(crypt.methods, [crypt.METHOD_BLOWFISH])
  48. else:
  49. self.assertEqual(crypt.methods[-1], crypt.METHOD_CRYPT)
  50. @unittest.skipUnless(
  51. crypt
  52. and (
  53. crypt.METHOD_SHA256 in crypt.methods or crypt.METHOD_SHA512 in crypt.methods
  54. ),
  55. 'requires support of SHA-2',
  56. )
  57. def test_sha2_rounds(self):
  58. for method in (crypt.METHOD_SHA256, crypt.METHOD_SHA512):
  59. for rounds in 1000, 10_000, 100_000:
  60. salt = crypt.mksalt(method, rounds=rounds)
  61. self.assertIn('$rounds=%d$' % rounds, salt)
  62. self.assertEqual(len(salt) - method.salt_chars,
  63. 11 + len(str(rounds)))
  64. cr = crypt.crypt('mypassword', salt)
  65. self.assertTrue(cr)
  66. cr2 = crypt.crypt('mypassword', cr)
  67. self.assertEqual(cr2, cr)
  68. @unittest.skipUnless(
  69. crypt and crypt.METHOD_BLOWFISH in crypt.methods, 'requires support of Blowfish'
  70. )
  71. def test_blowfish_rounds(self):
  72. for log_rounds in range(4, 11):
  73. salt = crypt.mksalt(crypt.METHOD_BLOWFISH, rounds=1 << log_rounds)
  74. self.assertIn('$%02d$' % log_rounds, salt)
  75. self.assertIn(len(salt) - crypt.METHOD_BLOWFISH.salt_chars, {6, 7})
  76. cr = crypt.crypt('mypassword', salt)
  77. self.assertTrue(cr)
  78. cr2 = crypt.crypt('mypassword', cr)
  79. self.assertEqual(cr2, cr)
  80. def test_invalid_rounds(self):
  81. for method in (crypt.METHOD_SHA256, crypt.METHOD_SHA512,
  82. crypt.METHOD_BLOWFISH):
  83. with self.assertRaises(TypeError):
  84. crypt.mksalt(method, rounds='4096')
  85. with self.assertRaises(TypeError):
  86. crypt.mksalt(method, rounds=4096.0)
  87. for rounds in (0, 1, -1, 1<<999):
  88. with self.assertRaises(ValueError):
  89. crypt.mksalt(method, rounds=rounds)
  90. with self.assertRaises(ValueError):
  91. crypt.mksalt(crypt.METHOD_BLOWFISH, rounds=1000)
  92. for method in (crypt.METHOD_CRYPT, crypt.METHOD_MD5):
  93. with self.assertRaisesRegex(ValueError, 'support'):
  94. crypt.mksalt(method, rounds=4096)
  95. if __name__ == "__main__":
  96. unittest.main()