test_KMAC.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. import unittest
  2. from binascii import unhexlify, hexlify
  3. from Crypto.Util.py3compat import tobytes
  4. from Crypto.Util.strxor import strxor_c
  5. from Crypto.SelfTest.st_common import list_test_cases
  6. from Crypto.Hash import KMAC128, KMAC256
  7. class KMACTest(unittest.TestCase):
  8. def new(self, *args, **kwargs):
  9. return self.KMAC.new(key=b'X' * (self.minimum_key_bits // 8), *args, **kwargs)
  10. def test_new_positive(self):
  11. key = b'X' * 32
  12. h = self.new()
  13. for new_func in self.KMAC.new, h.new:
  14. for dbytes in range(self.minimum_bytes, 128 + 1):
  15. hobj = new_func(key=key, mac_len=dbytes)
  16. self.assertEqual(hobj.digest_size, dbytes)
  17. digest1 = new_func(key=key, data=b"\x90").digest()
  18. digest2 = new_func(key=key).update(b"\x90").digest()
  19. self.assertEqual(digest1, digest2)
  20. new_func(data=b"A", key=key, custom=b"g")
  21. hobj = h.new(key=key)
  22. self.assertEqual(hobj.digest_size, self.default_bytes)
  23. def test_new_negative(self):
  24. h = self.new()
  25. for new_func in self.KMAC.new, h.new:
  26. self.assertRaises(ValueError, new_func, key=b'X'*32,
  27. mac_len=0)
  28. self.assertRaises(ValueError, new_func, key=b'X'*32,
  29. mac_len=self.minimum_bytes - 1)
  30. self.assertRaises(TypeError, new_func,
  31. key=u"string")
  32. self.assertRaises(TypeError, new_func,
  33. data=u"string")
  34. def test_default_digest_size(self):
  35. digest = self.new(data=b'abc').digest()
  36. self.assertEqual(len(digest), self.default_bytes)
  37. def test_update(self):
  38. pieces = [b"\x0A" * 200, b"\x14" * 300]
  39. h = self.new()
  40. h.update(pieces[0]).update(pieces[1])
  41. digest = h.digest()
  42. h = self.new()
  43. h.update(pieces[0] + pieces[1])
  44. self.assertEqual(h.digest(), digest)
  45. def test_update_negative(self):
  46. h = self.new()
  47. self.assertRaises(TypeError, h.update, u"string")
  48. def test_digest(self):
  49. h = self.new()
  50. digest = h.digest()
  51. # hexdigest does not change the state
  52. self.assertEqual(h.digest(), digest)
  53. # digest returns a byte string
  54. self.assertTrue(isinstance(digest, type(b"digest")))
  55. def test_update_after_digest(self):
  56. msg = b"rrrrttt"
  57. # Normally, update() cannot be done after digest()
  58. h = self.new(mac_len=32, data=msg[:4])
  59. dig1 = h.digest()
  60. self.assertRaises(TypeError, h.update, dig1)
  61. def test_hex_digest(self):
  62. mac = self.new()
  63. digest = mac.digest()
  64. hexdigest = mac.hexdigest()
  65. # hexdigest is equivalent to digest
  66. self.assertEqual(hexlify(digest), tobytes(hexdigest))
  67. # hexdigest does not change the state
  68. self.assertEqual(mac.hexdigest(), hexdigest)
  69. # hexdigest returns a string
  70. self.assertTrue(isinstance(hexdigest, type("digest")))
  71. def test_verify(self):
  72. h = self.new()
  73. mac = h.digest()
  74. h.verify(mac)
  75. wrong_mac = strxor_c(mac, 255)
  76. self.assertRaises(ValueError, h.verify, wrong_mac)
  77. def test_hexverify(self):
  78. h = self.new()
  79. mac = h.hexdigest()
  80. h.hexverify(mac)
  81. self.assertRaises(ValueError, h.hexverify, "4556")
  82. def test_oid(self):
  83. oid = "2.16.840.1.101.3.4.2." + self.oid_variant
  84. h = self.new()
  85. self.assertEqual(h.oid, oid)
  86. def test_bytearray(self):
  87. key = b'0' * 32
  88. data = b"\x00\x01\x02"
  89. # Data and key can be a bytearray (during initialization)
  90. key_ba = bytearray(key)
  91. data_ba = bytearray(data)
  92. h1 = self.KMAC.new(data=data, key=key)
  93. h2 = self.KMAC.new(data=data_ba, key=key_ba)
  94. key_ba[:1] = b'\xFF'
  95. data_ba[:1] = b'\xFF'
  96. self.assertEqual(h1.digest(), h2.digest())
  97. # Data can be a bytearray (during operation)
  98. data_ba = bytearray(data)
  99. h1 = self.new()
  100. h2 = self.new()
  101. h1.update(data)
  102. h2.update(data_ba)
  103. data_ba[:1] = b'\xFF'
  104. self.assertEqual(h1.digest(), h2.digest())
  105. def test_memoryview(self):
  106. key = b'0' * 32
  107. data = b"\x00\x01\x02"
  108. def get_mv_ro(data):
  109. return memoryview(data)
  110. def get_mv_rw(data):
  111. return memoryview(bytearray(data))
  112. for get_mv in (get_mv_ro, get_mv_rw):
  113. # Data and key can be a memoryview (during initialization)
  114. key_mv = get_mv(key)
  115. data_mv = get_mv(data)
  116. h1 = self.KMAC.new(data=data, key=key)
  117. h2 = self.KMAC.new(data=data_mv, key=key_mv)
  118. if not data_mv.readonly:
  119. data_mv[:1] = b'\xFF'
  120. key_mv[:1] = b'\xFF'
  121. self.assertEqual(h1.digest(), h2.digest())
  122. # Data can be a memoryview (during operation)
  123. data_mv = get_mv(data)
  124. h1 = self.new()
  125. h2 = self.new()
  126. h1.update(data)
  127. h2.update(data_mv)
  128. if not data_mv.readonly:
  129. data_mv[:1] = b'\xFF'
  130. self.assertEqual(h1.digest(), h2.digest())
  131. class KMAC128Test(KMACTest):
  132. KMAC = KMAC128
  133. minimum_key_bits = 128
  134. minimum_bytes = 8
  135. default_bytes = 64
  136. oid_variant = "19"
  137. class KMAC256Test(KMACTest):
  138. KMAC = KMAC256
  139. minimum_key_bits = 256
  140. minimum_bytes = 8
  141. default_bytes = 64
  142. oid_variant = "20"
  143. class NISTExampleTestVectors(unittest.TestCase):
  144. # https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/KMAC_samples.pdf
  145. test_data = [
  146. (
  147. "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F"
  148. "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F",
  149. "00 01 02 03",
  150. "",
  151. "E5 78 0B 0D 3E A6 F7 D3 A4 29 C5 70 6A A4 3A 00"
  152. "FA DB D7 D4 96 28 83 9E 31 87 24 3F 45 6E E1 4E",
  153. "Sample #1 NIST",
  154. KMAC128
  155. ),
  156. (
  157. "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F"
  158. "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F",
  159. "00 01 02 03",
  160. "My Tagged Application",
  161. "3B 1F BA 96 3C D8 B0 B5 9E 8C 1A 6D 71 88 8B 71"
  162. "43 65 1A F8 BA 0A 70 70 C0 97 9E 28 11 32 4A A5",
  163. "Sample #2 NIST",
  164. KMAC128
  165. ),
  166. (
  167. "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F"
  168. "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F",
  169. "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"
  170. "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F"
  171. "20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F"
  172. "30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F"
  173. "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F"
  174. "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F"
  175. "60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F"
  176. "70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F"
  177. "80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F"
  178. "90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F"
  179. "A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF"
  180. "B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF"
  181. "C0 C1 C2 C3 C4 C5 C6 C7",
  182. "My Tagged Application",
  183. "1F 5B 4E 6C CA 02 20 9E 0D CB 5C A6 35 B8 9A 15"
  184. "E2 71 EC C7 60 07 1D FD 80 5F AA 38 F9 72 92 30",
  185. "Sample #3 NIST",
  186. KMAC128
  187. ),
  188. (
  189. "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F"
  190. "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F",
  191. "00 01 02 03",
  192. "My Tagged Application",
  193. "20 C5 70 C3 13 46 F7 03 C9 AC 36 C6 1C 03 CB 64"
  194. "C3 97 0D 0C FC 78 7E 9B 79 59 9D 27 3A 68 D2 F7"
  195. "F6 9D 4C C3 DE 9D 10 4A 35 16 89 F2 7C F6 F5 95"
  196. "1F 01 03 F3 3F 4F 24 87 10 24 D9 C2 77 73 A8 DD",
  197. "Sample #4 NIST",
  198. KMAC256
  199. ),
  200. (
  201. "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F"
  202. "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F",
  203. "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"
  204. "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F"
  205. "20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F"
  206. "30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F"
  207. "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F"
  208. "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F"
  209. "60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F"
  210. "70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F"
  211. "80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F"
  212. "90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F"
  213. "A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF"
  214. "B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF"
  215. "C0 C1 C2 C3 C4 C5 C6 C7",
  216. "",
  217. "75 35 8C F3 9E 41 49 4E 94 97 07 92 7C EE 0A F2"
  218. "0A 3F F5 53 90 4C 86 B0 8F 21 CC 41 4B CF D6 91"
  219. "58 9D 27 CF 5E 15 36 9C BB FF 8B 9A 4C 2E B1 78"
  220. "00 85 5D 02 35 FF 63 5D A8 25 33 EC 6B 75 9B 69",
  221. "Sample #5 NIST",
  222. KMAC256
  223. ),
  224. (
  225. "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F"
  226. "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F",
  227. "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"
  228. "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F"
  229. "20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F"
  230. "30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F"
  231. "40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F"
  232. "50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F"
  233. "60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F"
  234. "70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F"
  235. "80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F"
  236. "90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F"
  237. "A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF"
  238. "B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF"
  239. "C0 C1 C2 C3 C4 C5 C6 C7",
  240. "My Tagged Application",
  241. "B5 86 18 F7 1F 92 E1 D5 6C 1B 8C 55 DD D7 CD 18"
  242. "8B 97 B4 CA 4D 99 83 1E B2 69 9A 83 7D A2 E4 D9"
  243. "70 FB AC FD E5 00 33 AE A5 85 F1 A2 70 85 10 C3"
  244. "2D 07 88 08 01 BD 18 28 98 FE 47 68 76 FC 89 65",
  245. "Sample #6 NIST",
  246. KMAC256
  247. ),
  248. ]
  249. def setUp(self):
  250. td = []
  251. for key, data, custom, mac, text, module in self.test_data:
  252. ni = (
  253. unhexlify(key.replace(" ", "")),
  254. unhexlify(data.replace(" ", "")),
  255. custom.encode(),
  256. unhexlify(mac.replace(" ", "")),
  257. text,
  258. module
  259. )
  260. td.append(ni)
  261. self.test_data = td
  262. def runTest(self):
  263. for key, data, custom, mac, text, module in self.test_data:
  264. h = module.new(data=data, key=key, custom=custom, mac_len=len(mac))
  265. mac_tag = h.digest()
  266. self.assertEqual(mac_tag, mac, msg=text)
  267. def get_tests(config={}):
  268. tests = []
  269. tests += list_test_cases(KMAC128Test)
  270. tests += list_test_cases(KMAC256Test)
  271. tests.append(NISTExampleTestVectors())
  272. return tests
  273. if __name__ == '__main__':
  274. def suite():
  275. return unittest.TestSuite(get_tests())
  276. unittest.main(defaultTest='suite')