test_KDF.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. # -*- coding: utf-8 -*-
  2. #
  3. # SelfTest/Protocol/test_KDF.py: Self-test for key derivation functions
  4. #
  5. # ===================================================================
  6. # The contents of this file are dedicated to the public domain. To
  7. # the extent that dedication to the public domain is not available,
  8. # everyone is granted a worldwide, perpetual, royalty-free,
  9. # non-exclusive license to exercise all rights associated with the
  10. # contents of this file for any purpose whatsoever.
  11. # No rights are reserved.
  12. #
  13. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  14. # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  15. # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  16. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  17. # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  18. # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  19. # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. # SOFTWARE.
  21. # ===================================================================
  22. import unittest
  23. from binascii import unhexlify
  24. from Cryptodome.Util.py3compat import *
  25. from Cryptodome.SelfTest.st_common import list_test_cases
  26. from Cryptodome.Hash import SHA1, HMAC, SHA256, MD5, SHA224, SHA384, SHA512
  27. from Cryptodome.Cipher import AES, DES3
  28. from Cryptodome.Protocol.KDF import PBKDF1, PBKDF2, _S2V, HKDF, scrypt
  29. def t2b(t):
  30. if t is None:
  31. return None
  32. t2 = t.replace(" ", "").replace("\n", "")
  33. return unhexlify(b(t2))
  34. class TestVector(object):
  35. pass
  36. class PBKDF1_Tests(unittest.TestCase):
  37. # List of tuples with test data.
  38. # Each tuple is made up by:
  39. # Item #0: a pass phrase
  40. # Item #1: salt (8 bytes encoded in hex)
  41. # Item #2: output key length
  42. # Item #3: iterations to use
  43. # Item #4: expected result (encoded in hex)
  44. _testData = (
  45. # From http://www.di-mgt.com.au/cryptoKDFs.html#examplespbkdf
  46. ("password","78578E5A5D63CB06",16,1000,"DC19847E05C64D2FAF10EBFB4A3D2A20"),
  47. )
  48. def test1(self):
  49. v = self._testData[0]
  50. res = PBKDF1(v[0], t2b(v[1]), v[2], v[3], SHA1)
  51. self.assertEqual(res, t2b(v[4]))
  52. class PBKDF2_Tests(unittest.TestCase):
  53. # List of tuples with test data.
  54. # Each tuple is made up by:
  55. # Item #0: a pass phrase
  56. # Item #1: salt (encoded in hex)
  57. # Item #2: output key length
  58. # Item #3: iterations to use
  59. # Item #4: hash module
  60. # Item #5: expected result (encoded in hex)
  61. _testData = (
  62. # From http://www.di-mgt.com.au/cryptoKDFs.html#examplespbkdf
  63. ("password","78578E5A5D63CB06",24,2048, SHA1, "BFDE6BE94DF7E11DD409BCE20A0255EC327CB936FFE93643"),
  64. # From RFC 6050
  65. ("password","73616c74", 20, 1, SHA1, "0c60c80f961f0e71f3a9b524af6012062fe037a6"),
  66. ("password","73616c74", 20, 2, SHA1, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957"),
  67. ("password","73616c74", 20, 4096, SHA1, "4b007901b765489abead49d926f721d065a429c1"),
  68. ("passwordPASSWORDpassword","73616c7453414c5473616c7453414c5473616c7453414c5473616c7453414c5473616c74",
  69. 25, 4096, SHA1, "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038"),
  70. ( 'pass\x00word',"7361006c74",16,4096, SHA1, "56fa6aa75548099dcc37d7f03425e0c3"),
  71. # From draft-josefsson-scrypt-kdf-01, Chapter 10
  72. ( 'passwd', '73616c74', 64, 1, SHA256, "55ac046e56e3089fec1691c22544b605f94185216dde0465e68b9d57c20dacbc49ca9cccf179b645991664b39d77ef317c71b845b1e30bd509112041d3a19783"),
  73. ( 'Password', '4e61436c', 64, 80000, SHA256, "4ddcd8f60b98be21830cee5ef22701f9641a4418d04c0414aeff08876b34ab56a1d425a1225833549adb841b51c9b3176a272bdebba1d078478f62b397f33c8d"),
  74. )
  75. def test1(self):
  76. # Test only for HMAC-SHA1 as PRF
  77. def prf_SHA1(p,s):
  78. return HMAC.new(p,s,SHA1).digest()
  79. def prf_SHA256(p,s):
  80. return HMAC.new(p,s,SHA256).digest()
  81. for i in range(len(self._testData)):
  82. v = self._testData[i]
  83. password = v[0]
  84. salt = t2b(v[1])
  85. out_len = v[2]
  86. iters = v[3]
  87. hash_mod = v[4]
  88. expected = t2b(v[5])
  89. if hash_mod is SHA1:
  90. res = PBKDF2(password, salt, out_len, iters)
  91. self.assertEqual(res, expected)
  92. res = PBKDF2(password, salt, out_len, iters, prf_SHA1)
  93. self.assertEqual(res, expected)
  94. else:
  95. res = PBKDF2(password, salt, out_len, iters, prf_SHA256)
  96. self.assertEqual(res, expected)
  97. def test2(self):
  98. # Verify that prf and hmac_hash_module are mutual exclusive
  99. def prf_SHA1(p,s):
  100. return HMAC.new(p,s,SHA1).digest()
  101. self.assertRaises(ValueError, PBKDF2, b("xxx"), b("yyy"), 16, 100,
  102. prf=prf_SHA1, hmac_hash_module=SHA1)
  103. def test3(self):
  104. # Verify that hmac_hash_module works like prf
  105. password = b("xxx")
  106. salt = b("yyy")
  107. for hashmod in (MD5, SHA1, SHA224, SHA256, SHA384, SHA512):
  108. pr1 = PBKDF2(password, salt, 16, 100,
  109. prf=lambda p, s: HMAC.new(p,s,hashmod).digest())
  110. pr2 = PBKDF2(password, salt, 16, 100, hmac_hash_module=hashmod)
  111. self.assertEqual(pr1, pr2)
  112. def test4(self):
  113. # Verify that PBKDF2 can take bytes or strings as password or salt
  114. k1 = PBKDF2("xxx", b("yyy"), 16, 10)
  115. k2 = PBKDF2(b("xxx"), b("yyy"), 16, 10)
  116. self.assertEqual(k1, k2)
  117. k1 = PBKDF2(b("xxx"), "yyy", 16, 10)
  118. k2 = PBKDF2(b("xxx"), b("yyy"), 16, 10)
  119. self.assertEqual(k1, k2)
  120. class S2V_Tests(unittest.TestCase):
  121. # Sequence of test vectors.
  122. # Each test vector is made up by:
  123. # Item #0: a tuple of strings
  124. # Item #1: an AES key
  125. # Item #2: the result
  126. # Item #3: the cipher module S2V is based on
  127. # Everything is hex encoded
  128. _testData = [
  129. # RFC5297, A.1
  130. (
  131. ( '101112131415161718191a1b1c1d1e1f2021222324252627',
  132. '112233445566778899aabbccddee' ),
  133. 'fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0',
  134. '85632d07c6e8f37f950acd320a2ecc93',
  135. AES
  136. ),
  137. # RFC5297, A.2
  138. (
  139. ( '00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddcc'+
  140. 'bbaa99887766554433221100',
  141. '102030405060708090a0',
  142. '09f911029d74e35bd84156c5635688c0',
  143. '7468697320697320736f6d6520706c61'+
  144. '696e7465787420746f20656e63727970'+
  145. '74207573696e67205349562d414553'),
  146. '7f7e7d7c7b7a79787776757473727170',
  147. '7bdb6e3b432667eb06f4d14bff2fbd0f',
  148. AES
  149. ),
  150. ]
  151. def test1(self):
  152. """Verify correctness of test vector"""
  153. for tv in self._testData:
  154. s2v = _S2V.new(t2b(tv[1]), tv[3])
  155. for s in tv[0]:
  156. s2v.update(t2b(s))
  157. result = s2v.derive()
  158. self.assertEqual(result, t2b(tv[2]))
  159. def test2(self):
  160. """Verify that no more than 127(AES) and 63(TDES)
  161. components are accepted."""
  162. key = bchr(0) * 8 + bchr(255) * 8
  163. for module in (AES, DES3):
  164. s2v = _S2V.new(key, module)
  165. max_comps = module.block_size*8-1
  166. for i in range(max_comps):
  167. s2v.update(b("XX"))
  168. self.assertRaises(TypeError, s2v.update, b("YY"))
  169. class HKDF_Tests(unittest.TestCase):
  170. # Test vectors from RFC5869, Appendix A
  171. # Each tuple is made up by:
  172. # Item #0: hash module
  173. # Item #1: secret
  174. # Item #2: salt
  175. # Item #3: context
  176. # Item #4: expected result
  177. _test_vector = (
  178. (
  179. SHA256,
  180. "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
  181. "000102030405060708090a0b0c",
  182. "f0f1f2f3f4f5f6f7f8f9",
  183. 42,
  184. "3cb25f25faacd57a90434f64d0362f2a" +
  185. "2d2d0a90cf1a5a4c5db02d56ecc4c5bf" +
  186. "34007208d5b887185865"
  187. ),
  188. (
  189. SHA256,
  190. "000102030405060708090a0b0c0d0e0f" +
  191. "101112131415161718191a1b1c1d1e1f" +
  192. "202122232425262728292a2b2c2d2e2f" +
  193. "303132333435363738393a3b3c3d3e3f" +
  194. "404142434445464748494a4b4c4d4e4f",
  195. "606162636465666768696a6b6c6d6e6f" +
  196. "707172737475767778797a7b7c7d7e7f" +
  197. "808182838485868788898a8b8c8d8e8f" +
  198. "909192939495969798999a9b9c9d9e9f" +
  199. "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf",
  200. "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" +
  201. "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" +
  202. "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" +
  203. "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" +
  204. "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
  205. 82,
  206. "b11e398dc80327a1c8e7f78c596a4934" +
  207. "4f012eda2d4efad8a050cc4c19afa97c" +
  208. "59045a99cac7827271cb41c65e590e09" +
  209. "da3275600c2f09b8367793a9aca3db71" +
  210. "cc30c58179ec3e87c14c01d5c1f3434f" +
  211. "1d87"
  212. ),
  213. (
  214. SHA256,
  215. "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
  216. None,
  217. None,
  218. 42,
  219. "8da4e775a563c18f715f802a063c5a31" +
  220. "b8a11f5c5ee1879ec3454e5f3c738d2d" +
  221. "9d201395faa4b61a96c8"
  222. ),
  223. (
  224. SHA1,
  225. "0b0b0b0b0b0b0b0b0b0b0b",
  226. "000102030405060708090a0b0c",
  227. "f0f1f2f3f4f5f6f7f8f9",
  228. 42,
  229. "085a01ea1b10f36933068b56efa5ad81" +
  230. "a4f14b822f5b091568a9cdd4f155fda2" +
  231. "c22e422478d305f3f896"
  232. ),
  233. (
  234. SHA1,
  235. "000102030405060708090a0b0c0d0e0f" +
  236. "101112131415161718191a1b1c1d1e1f" +
  237. "202122232425262728292a2b2c2d2e2f" +
  238. "303132333435363738393a3b3c3d3e3f" +
  239. "404142434445464748494a4b4c4d4e4f",
  240. "606162636465666768696a6b6c6d6e6f" +
  241. "707172737475767778797a7b7c7d7e7f" +
  242. "808182838485868788898a8b8c8d8e8f" +
  243. "909192939495969798999a9b9c9d9e9f" +
  244. "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf",
  245. "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" +
  246. "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" +
  247. "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" +
  248. "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" +
  249. "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
  250. 82,
  251. "0bd770a74d1160f7c9f12cd5912a06eb" +
  252. "ff6adcae899d92191fe4305673ba2ffe" +
  253. "8fa3f1a4e5ad79f3f334b3b202b2173c" +
  254. "486ea37ce3d397ed034c7f9dfeb15c5e" +
  255. "927336d0441f4c4300e2cff0d0900b52" +
  256. "d3b4"
  257. ),
  258. (
  259. SHA1,
  260. "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
  261. "",
  262. "",
  263. 42,
  264. "0ac1af7002b3d761d1e55298da9d0506" +
  265. "b9ae52057220a306e07b6b87e8df21d0" +
  266. "ea00033de03984d34918"
  267. ),
  268. (
  269. SHA1,
  270. "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
  271. None,
  272. "",
  273. 42,
  274. "2c91117204d745f3500d636a62f64f0a" +
  275. "b3bae548aa53d423b0d1f27ebba6f5e5" +
  276. "673a081d70cce7acfc48"
  277. )
  278. )
  279. def test1(self):
  280. for tv in self._test_vector:
  281. secret, salt, info, exp = [ t2b(tv[x]) for x in (1,2,3,5) ]
  282. key_len, hashmod = [ tv[x] for x in (4,0) ]
  283. output = HKDF(secret, key_len, salt, hashmod, 1, info)
  284. self.assertEqual(output, exp)
  285. def test2(self):
  286. ref = HKDF(b("XXXXXX"), 12, b("YYYY"), SHA1)
  287. # Same output, but this time split over 2 keys
  288. key1, key2 = HKDF(b("XXXXXX"), 6, b("YYYY"), SHA1, 2)
  289. self.assertEqual((ref[:6], ref[6:]), (key1, key2))
  290. # Same output, but this time split over 3 keys
  291. key1, key2, key3 = HKDF(b("XXXXXX"), 4, b("YYYY"), SHA1, 3)
  292. self.assertEqual((ref[:4], ref[4:8], ref[8:]), (key1, key2, key3))
  293. class scrypt_Tests(unittest.TestCase):
  294. # Test vectors taken from
  295. # https://tools.ietf.org/html/rfc7914
  296. # - password
  297. # - salt
  298. # - N
  299. # - r
  300. # - p
  301. data = (
  302. (
  303. "",
  304. "",
  305. 16, # 2K
  306. 1,
  307. 1,
  308. """
  309. 77 d6 57 62 38 65 7b 20 3b 19 ca 42 c1 8a 04 97
  310. f1 6b 48 44 e3 07 4a e8 df df fa 3f ed e2 14 42
  311. fc d0 06 9d ed 09 48 f8 32 6a 75 3a 0f c8 1f 17
  312. e8 d3 e0 fb 2e 0d 36 28 cf 35 e2 0c 38 d1 89 06
  313. """
  314. ),
  315. (
  316. "password",
  317. "NaCl",
  318. 1024, # 1M
  319. 8,
  320. 16,
  321. """
  322. fd ba be 1c 9d 34 72 00 78 56 e7 19 0d 01 e9 fe
  323. 7c 6a d7 cb c8 23 78 30 e7 73 76 63 4b 37 31 62
  324. 2e af 30 d9 2e 22 a3 88 6f f1 09 27 9d 98 30 da
  325. c7 27 af b9 4a 83 ee 6d 83 60 cb df a2 cc 06 40
  326. """
  327. ),
  328. (
  329. "pleaseletmein",
  330. "SodiumChloride",
  331. 16384, # 16M
  332. 8,
  333. 1,
  334. """
  335. 70 23 bd cb 3a fd 73 48 46 1c 06 cd 81 fd 38 eb
  336. fd a8 fb ba 90 4f 8e 3e a9 b5 43 f6 54 5d a1 f2
  337. d5 43 29 55 61 3f 0f cf 62 d4 97 05 24 2a 9a f9
  338. e6 1e 85 dc 0d 65 1e 40 df cf 01 7b 45 57 58 87
  339. """
  340. ),
  341. (
  342. "pleaseletmein",
  343. "SodiumChloride",
  344. 1048576, # 1G
  345. 8,
  346. 1,
  347. """
  348. 21 01 cb 9b 6a 51 1a ae ad db be 09 cf 70 f8 81
  349. ec 56 8d 57 4a 2f fd 4d ab e5 ee 98 20 ad aa 47
  350. 8e 56 fd 8f 4b a5 d0 9f fa 1c 6d 92 7c 40 f4 c3
  351. 37 30 40 49 e8 a9 52 fb cb f4 5c 6f a7 7a 41 a4
  352. """
  353. ),
  354. )
  355. def setUp(self):
  356. new_test_vectors = []
  357. for tv in self.data:
  358. new_tv = TestVector()
  359. new_tv.P = b(tv[0])
  360. new_tv.S = b(tv[1])
  361. new_tv.N = tv[2]
  362. new_tv.r = tv[3]
  363. new_tv.p = tv[4]
  364. new_tv.output = t2b(tv[5])
  365. new_tv.dkLen = len(new_tv.output)
  366. new_test_vectors.append(new_tv)
  367. self.data = new_test_vectors
  368. def test2(self):
  369. for tv in self.data:
  370. try:
  371. output = scrypt(tv.P, tv.S, tv.dkLen, tv.N, tv.r, tv.p)
  372. except ValueError as e:
  373. if " 2 " in str(e) and tv.N >= 1048576:
  374. import warnings
  375. warnings.warn("Not enough memory to unit test scrypt() with N=1048576", RuntimeWarning)
  376. continue
  377. else:
  378. raise e
  379. self.assertEqual(output, tv.output)
  380. def test3(self):
  381. ref = scrypt(b("password"), b("salt"), 12, 16, 1, 1)
  382. # Same output, but this time split over 2 keys
  383. key1, key2 = scrypt(b("password"), b("salt"), 6, 16, 1, 1, 2)
  384. self.assertEqual((ref[:6], ref[6:]), (key1, key2))
  385. # Same output, but this time split over 3 keys
  386. key1, key2, key3 = scrypt(b("password"), b("salt"), 4, 16, 1, 1, 3)
  387. self.assertEqual((ref[:4], ref[4:8], ref[8:]), (key1, key2, key3))
  388. def get_tests(config={}):
  389. if not config.get('slow_tests'):
  390. PBKDF2_Tests._testData = PBKDF2_Tests._testData[:3]
  391. scrypt_Tests.data = scrypt_Tests.data[:3]
  392. tests = []
  393. tests += list_test_cases(PBKDF1_Tests)
  394. tests += list_test_cases(PBKDF2_Tests)
  395. tests += list_test_cases(S2V_Tests)
  396. tests += list_test_cases(HKDF_Tests)
  397. tests += list_test_cases(scrypt_Tests)
  398. return tests
  399. if __name__ == '__main__':
  400. suite = lambda: unittest.TestSuite(get_tests())
  401. unittest.main(defaultTest='suite')
  402. # vim:set ts=4 sw=4 sts=4