test_TupleHash.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. import unittest
  2. from binascii import unhexlify, hexlify
  3. from Crypto.Util.py3compat import tobytes
  4. from Crypto.SelfTest.st_common import list_test_cases
  5. from Crypto.Hash import TupleHash128, TupleHash256
  6. class TupleHashTest(unittest.TestCase):
  7. def new(self, *args, **kwargs):
  8. return self.TupleHash.new(*args, **kwargs)
  9. def test_new_positive(self):
  10. h = self.new()
  11. for new_func in self.TupleHash.new, h.new:
  12. for dbits in range(64, 1024 + 1, 8):
  13. hobj = new_func(digest_bits=dbits)
  14. self.assertEqual(hobj.digest_size * 8, dbits)
  15. for dbytes in range(8, 128 + 1):
  16. hobj = new_func(digest_bytes=dbytes)
  17. self.assertEqual(hobj.digest_size, dbytes)
  18. hobj = h.new()
  19. self.assertEqual(hobj.digest_size, self.default_bytes)
  20. def test_new_negative(self):
  21. h = self.new()
  22. for new_func in self.TupleHash.new, h.new:
  23. self.assertRaises(TypeError, new_func,
  24. digest_bytes=self.minimum_bytes,
  25. digest_bits=self.minimum_bits)
  26. self.assertRaises(ValueError, new_func, digest_bytes=0)
  27. self.assertRaises(ValueError, new_func,
  28. digest_bits=self.minimum_bits + 7)
  29. self.assertRaises(ValueError, new_func,
  30. digest_bits=self.minimum_bits - 8)
  31. self.assertRaises(ValueError, new_func,
  32. digest_bits=self.minimum_bytes - 1)
  33. def test_default_digest_size(self):
  34. digest = self.new().digest()
  35. self.assertEqual(len(digest), self.default_bytes)
  36. def test_update(self):
  37. h = self.new()
  38. h.update(b'')
  39. h.digest()
  40. h = self.new()
  41. h.update(b'')
  42. h.update(b'STRING1')
  43. h.update(b'STRING2')
  44. mac1 = h.digest()
  45. h = self.new()
  46. h.update(b'STRING1')
  47. h.update(b'STRING2')
  48. mac2 = h.digest()
  49. self.assertNotEqual(mac1, mac2)
  50. h = self.new()
  51. h.update(b'STRING1', b'STRING2')
  52. self.assertEqual(mac2, h.digest())
  53. h = self.new()
  54. t = b'STRING1', b'STRING2'
  55. h.update(*t)
  56. self.assertEqual(mac2, h.digest())
  57. def test_update_negative(self):
  58. h = self.new()
  59. self.assertRaises(TypeError, h.update, u"string")
  60. self.assertRaises(TypeError, h.update, None)
  61. self.assertRaises(TypeError, h.update, (b'STRING1', b'STRING2'))
  62. def test_digest(self):
  63. h = self.new()
  64. digest = h.digest()
  65. # hexdigest does not change the state
  66. self.assertEqual(h.digest(), digest)
  67. # digest returns a byte string
  68. self.assertTrue(isinstance(digest, type(b"digest")))
  69. def test_update_after_digest(self):
  70. msg = b"rrrrttt"
  71. # Normally, update() cannot be done after digest()
  72. h = self.new()
  73. h.update(msg)
  74. dig1 = h.digest()
  75. self.assertRaises(TypeError, h.update, dig1)
  76. def test_hex_digest(self):
  77. mac = self.new()
  78. digest = mac.digest()
  79. hexdigest = mac.hexdigest()
  80. # hexdigest is equivalent to digest
  81. self.assertEqual(hexlify(digest), tobytes(hexdigest))
  82. # hexdigest does not change the state
  83. self.assertEqual(mac.hexdigest(), hexdigest)
  84. # hexdigest returns a string
  85. self.assertTrue(isinstance(hexdigest, type("digest")))
  86. def test_bytearray(self):
  87. data = b"\x00\x01\x02"
  88. # Data can be a bytearray (during operation)
  89. data_ba = bytearray(data)
  90. h1 = self.new()
  91. h2 = self.new()
  92. h1.update(data)
  93. h2.update(data_ba)
  94. data_ba[:1] = b'\xFF'
  95. self.assertEqual(h1.digest(), h2.digest())
  96. def test_memoryview(self):
  97. data = b"\x00\x01\x02"
  98. def get_mv_ro(data):
  99. return memoryview(data)
  100. def get_mv_rw(data):
  101. return memoryview(bytearray(data))
  102. for get_mv in (get_mv_ro, get_mv_rw):
  103. # Data can be a memoryview (during operation)
  104. data_mv = get_mv(data)
  105. h1 = self.new()
  106. h2 = self.new()
  107. h1.update(data)
  108. h2.update(data_mv)
  109. if not data_mv.readonly:
  110. data_mv[:1] = b'\xFF'
  111. self.assertEqual(h1.digest(), h2.digest())
  112. class TupleHash128Test(TupleHashTest):
  113. TupleHash = TupleHash128
  114. minimum_bytes = 8
  115. default_bytes = 64
  116. minimum_bits = 64
  117. default_bits = 512
  118. class TupleHash256Test(TupleHashTest):
  119. TupleHash = TupleHash256
  120. minimum_bytes = 8
  121. default_bytes = 64
  122. minimum_bits = 64
  123. default_bits = 512
  124. class NISTExampleTestVectors(unittest.TestCase):
  125. # http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TupleHash_samples.pdf
  126. test_data = [
  127. (
  128. (
  129. "00 01 02",
  130. "10 11 12 13 14 15",
  131. ),
  132. "",
  133. "C5 D8 78 6C 1A FB 9B 82 11 1A B3 4B 65 B2 C0 04"
  134. "8F A6 4E 6D 48 E2 63 26 4C E1 70 7D 3F FC 8E D1",
  135. "KMAC128 Sample #1 NIST",
  136. TupleHash128
  137. ),
  138. (
  139. (
  140. "00 01 02",
  141. "10 11 12 13 14 15",
  142. ),
  143. "My Tuple App",
  144. "75 CD B2 0F F4 DB 11 54 E8 41 D7 58 E2 41 60 C5"
  145. "4B AE 86 EB 8C 13 E7 F5 F4 0E B3 55 88 E9 6D FB",
  146. "KMAC128 Sample #2 NIST",
  147. TupleHash128
  148. ),
  149. (
  150. (
  151. "00 01 02",
  152. "10 11 12 13 14 15",
  153. "20 21 22 23 24 25 26 27 28",
  154. ),
  155. "My Tuple App",
  156. "E6 0F 20 2C 89 A2 63 1E DA 8D 4C 58 8C A5 FD 07"
  157. "F3 9E 51 51 99 8D EC CF 97 3A DB 38 04 BB 6E 84",
  158. "KMAC128 Sample #3 NIST",
  159. TupleHash128
  160. ),
  161. (
  162. (
  163. "00 01 02",
  164. "10 11 12 13 14 15",
  165. ),
  166. "",
  167. "CF B7 05 8C AC A5 E6 68 F8 1A 12 A2 0A 21 95 CE"
  168. "97 A9 25 F1 DB A3 E7 44 9A 56 F8 22 01 EC 60 73"
  169. "11 AC 26 96 B1 AB 5E A2 35 2D F1 42 3B DE 7B D4"
  170. "BB 78 C9 AE D1 A8 53 C7 86 72 F9 EB 23 BB E1 94",
  171. "KMAC256 Sample #4 NIST",
  172. TupleHash256
  173. ),
  174. (
  175. (
  176. "00 01 02",
  177. "10 11 12 13 14 15",
  178. ),
  179. "My Tuple App",
  180. "14 7C 21 91 D5 ED 7E FD 98 DB D9 6D 7A B5 A1 16"
  181. "92 57 6F 5F E2 A5 06 5F 3E 33 DE 6B BA 9F 3A A1"
  182. "C4 E9 A0 68 A2 89 C6 1C 95 AA B3 0A EE 1E 41 0B"
  183. "0B 60 7D E3 62 0E 24 A4 E3 BF 98 52 A1 D4 36 7E",
  184. "KMAC256 Sample #5 NIST",
  185. TupleHash256
  186. ),
  187. (
  188. (
  189. "00 01 02",
  190. "10 11 12 13 14 15",
  191. "20 21 22 23 24 25 26 27 28",
  192. ),
  193. "My Tuple App",
  194. "45 00 0B E6 3F 9B 6B FD 89 F5 47 17 67 0F 69 A9"
  195. "BC 76 35 91 A4 F0 5C 50 D6 88 91 A7 44 BC C6 E7"
  196. "D6 D5 B5 E8 2C 01 8D A9 99 ED 35 B0 BB 49 C9 67"
  197. "8E 52 6A BD 8E 85 C1 3E D2 54 02 1D B9 E7 90 CE",
  198. "KMAC256 Sample #6 NIST",
  199. TupleHash256
  200. ),
  201. ]
  202. def setUp(self):
  203. td = []
  204. for tv_in in self.test_data:
  205. tv_out = [None] * len(tv_in)
  206. tv_out[0] = []
  207. for string in tv_in[0]:
  208. tv_out[0].append(unhexlify(string.replace(" ", "")))
  209. tv_out[1] = tobytes(tv_in[1]) # Custom
  210. tv_out[2] = unhexlify(tv_in[2].replace(" ", ""))
  211. tv_out[3] = tv_in[3]
  212. tv_out[4] = tv_in[4]
  213. td.append(tv_out)
  214. self.test_data = td
  215. def runTest(self):
  216. for data, custom, digest, text, module in self.test_data:
  217. hd1 = module.new(custom=custom, digest_bytes=len(digest))
  218. hd2 = module.new(custom=custom, digest_bytes=len(digest))
  219. # Call update() for each element
  220. for string in data:
  221. hd1.update(string)
  222. # One single update for all elements
  223. hd2.update(*data)
  224. self.assertEqual(hd1.digest(), digest, msg=text)
  225. self.assertEqual(hd2.digest(), digest, msg=text)
  226. def get_tests(config={}):
  227. tests = []
  228. tests += list_test_cases(TupleHash128Test)
  229. tests += list_test_cases(TupleHash256Test)
  230. tests.append(NISTExampleTestVectors())
  231. return tests
  232. if __name__ == '__main__':
  233. def suite():
  234. return unittest.TestSuite(get_tests())
  235. unittest.main(defaultTest='suite')