test_KangarooTwelve.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. # ===================================================================
  2. # Redistribution and use in source and binary forms, with or without
  3. # modification, are permitted provided that the following conditions
  4. # are met:
  5. #
  6. # 1. Redistributions of source code must retain the above copyright
  7. # notice, this list of conditions and the following disclaimer.
  8. # 2. Redistributions in binary form must reproduce the above copyright
  9. # notice, this list of conditions and the following disclaimer in
  10. # the documentation and/or other materials provided with the
  11. # distribution.
  12. #
  13. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  14. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  15. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  16. # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  17. # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  18. # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  19. # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  20. # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  21. # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  22. # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  23. # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  24. # POSSIBILITY OF SUCH DAMAGE.
  25. # ===================================================================
  26. """Self-test suite for Crypto.Hash.KangarooTwelve"""
  27. import unittest
  28. from binascii import unhexlify
  29. from Crypto.SelfTest.st_common import list_test_cases
  30. from Crypto.Hash import KangarooTwelve as K12
  31. from Crypto.Util.py3compat import b, bchr
  32. class KangarooTwelveTest(unittest.TestCase):
  33. def test_length_encode(self):
  34. self.assertEqual(K12._length_encode(0), b'\x00')
  35. self.assertEqual(K12._length_encode(12), b'\x0C\x01')
  36. self.assertEqual(K12._length_encode(65538), b'\x01\x00\x02\x03')
  37. def test_new_positive(self):
  38. xof1 = K12.new()
  39. xof2 = K12.new(data=b("90"))
  40. xof3 = K12.new().update(b("90"))
  41. self.assertNotEqual(xof1.read(10), xof2.read(10))
  42. xof3.read(10)
  43. self.assertEqual(xof2.read(10), xof3.read(10))
  44. xof1 = K12.new()
  45. ref = xof1.read(10)
  46. xof2 = K12.new(custom=b(""))
  47. xof3 = K12.new(custom=b("foo"))
  48. self.assertEqual(ref, xof2.read(10))
  49. self.assertNotEqual(ref, xof3.read(10))
  50. xof1 = K12.new(custom=b("foo"))
  51. xof2 = K12.new(custom=b("foo"), data=b("90"))
  52. xof3 = K12.new(custom=b("foo")).update(b("90"))
  53. self.assertNotEqual(xof1.read(10), xof2.read(10))
  54. xof3.read(10)
  55. self.assertEqual(xof2.read(10), xof3.read(10))
  56. def test_update(self):
  57. pieces = [bchr(10) * 200, bchr(20) * 300]
  58. h = K12.new()
  59. h.update(pieces[0]).update(pieces[1])
  60. digest = h.read(10)
  61. h = K12.new()
  62. h.update(pieces[0] + pieces[1])
  63. self.assertEqual(h.read(10), digest)
  64. def test_update_negative(self):
  65. h = K12.new()
  66. self.assertRaises(TypeError, h.update, u"string")
  67. def test_digest(self):
  68. h = K12.new()
  69. digest = h.read(90)
  70. # read returns a byte string of the right length
  71. self.assertTrue(isinstance(digest, type(b("digest"))))
  72. self.assertEqual(len(digest), 90)
  73. def test_update_after_read(self):
  74. mac = K12.new()
  75. mac.update(b("rrrr"))
  76. mac.read(90)
  77. self.assertRaises(TypeError, mac.update, b("ttt"))
  78. def txt2bin(txt):
  79. clean = txt.replace(" ", "").replace("\n", "").replace("\r", "")
  80. return unhexlify(clean)
  81. def ptn(n):
  82. res = bytearray(n)
  83. pattern = b"".join([bchr(x) for x in range(0, 0xFB)])
  84. for base in range(0, n - 0xFB, 0xFB):
  85. res[base:base + 0xFB] = pattern
  86. remain = n % 0xFB
  87. if remain:
  88. base = (n // 0xFB) * 0xFB
  89. res[base:] = pattern[:remain]
  90. assert(len(res) == n)
  91. return res
  92. def chunked(source, size):
  93. for i in range(0, len(source), size):
  94. yield source[i:i+size]
  95. class KangarooTwelveTV(unittest.TestCase):
  96. # https://github.com/XKCP/XKCP/blob/master/tests/TestVectors/KangarooTwelve.txt
  97. def test_zero_1(self):
  98. tv = """1A C2 D4 50 FC 3B 42 05 D1 9D A7 BF CA 1B 37 51
  99. 3C 08 03 57 7A C7 16 7F 06 FE 2C E1 F0 EF 39 E5"""
  100. btv = txt2bin(tv)
  101. res = K12.new().read(32)
  102. self.assertEqual(res, btv)
  103. def test_zero_2(self):
  104. tv = """1A C2 D4 50 FC 3B 42 05 D1 9D A7 BF CA 1B 37 51
  105. 3C 08 03 57 7A C7 16 7F 06 FE 2C E1 F0 EF 39 E5
  106. 42 69 C0 56 B8 C8 2E 48 27 60 38 B6 D2 92 96 6C
  107. C0 7A 3D 46 45 27 2E 31 FF 38 50 81 39 EB 0A 71"""
  108. btv = txt2bin(tv)
  109. res = K12.new().read(64)
  110. self.assertEqual(res, btv)
  111. def test_zero_3(self):
  112. tv = """E8 DC 56 36 42 F7 22 8C 84 68 4C 89 84 05 D3 A8
  113. 34 79 91 58 C0 79 B1 28 80 27 7A 1D 28 E2 FF 6D"""
  114. btv = txt2bin(tv)
  115. res = K12.new().read(10032)
  116. self.assertEqual(res[-32:], btv)
  117. def test_ptn_1(self):
  118. tv = """2B DA 92 45 0E 8B 14 7F 8A 7C B6 29 E7 84 A0 58
  119. EF CA 7C F7 D8 21 8E 02 D3 45 DF AA 65 24 4A 1F"""
  120. btv = txt2bin(tv)
  121. res = K12.new(data=ptn(1)).read(32)
  122. self.assertEqual(res, btv)
  123. def test_ptn_17(self):
  124. tv = """6B F7 5F A2 23 91 98 DB 47 72 E3 64 78 F8 E1 9B
  125. 0F 37 12 05 F6 A9 A9 3A 27 3F 51 DF 37 12 28 88"""
  126. btv = txt2bin(tv)
  127. res = K12.new(data=ptn(17)).read(32)
  128. self.assertEqual(res, btv)
  129. def test_ptn_17_2(self):
  130. tv = """0C 31 5E BC DE DB F6 14 26 DE 7D CF 8F B7 25 D1
  131. E7 46 75 D7 F5 32 7A 50 67 F3 67 B1 08 EC B6 7C"""
  132. btv = txt2bin(tv)
  133. res = K12.new(data=ptn(17**2)).read(32)
  134. self.assertEqual(res, btv)
  135. def test_ptn_17_3(self):
  136. tv = """CB 55 2E 2E C7 7D 99 10 70 1D 57 8B 45 7D DF 77
  137. 2C 12 E3 22 E4 EE 7F E4 17 F9 2C 75 8F 0D 59 D0"""
  138. btv = txt2bin(tv)
  139. res = K12.new(data=ptn(17**3)).read(32)
  140. self.assertEqual(res, btv)
  141. def test_ptn_17_4(self):
  142. tv = """87 01 04 5E 22 20 53 45 FF 4D DA 05 55 5C BB 5C
  143. 3A F1 A7 71 C2 B8 9B AE F3 7D B4 3D 99 98 B9 FE"""
  144. btv = txt2bin(tv)
  145. data = ptn(17**4)
  146. # All at once
  147. res = K12.new(data=data).read(32)
  148. self.assertEqual(res, btv)
  149. # Byte by byte
  150. k12 = K12.new()
  151. for x in data:
  152. k12.update(bchr(x))
  153. res = k12.read(32)
  154. self.assertEqual(res, btv)
  155. # Chunks of various prime sizes
  156. for chunk_size in (13, 17, 19, 23, 31):
  157. k12 = K12.new()
  158. for x in chunked(data, chunk_size):
  159. k12.update(x)
  160. res = k12.read(32)
  161. self.assertEqual(res, btv)
  162. def test_ptn_17_5(self):
  163. tv = """84 4D 61 09 33 B1 B9 96 3C BD EB 5A E3 B6 B0 5C
  164. C7 CB D6 7C EE DF 88 3E B6 78 A0 A8 E0 37 16 82"""
  165. btv = txt2bin(tv)
  166. data = ptn(17**5)
  167. # All at once
  168. res = K12.new(data=data).read(32)
  169. self.assertEqual(res, btv)
  170. # Chunks
  171. k12 = K12.new()
  172. for chunk in chunked(data, 8192):
  173. k12.update(chunk)
  174. res = k12.read(32)
  175. self.assertEqual(res, btv)
  176. def test_ptn_17_6(self):
  177. tv = """3C 39 07 82 A8 A4 E8 9F A6 36 7F 72 FE AA F1 32
  178. 55 C8 D9 58 78 48 1D 3C D8 CE 85 F5 8E 88 0A F8"""
  179. btv = txt2bin(tv)
  180. data = ptn(17**6)
  181. # All at once
  182. res = K12.new(data=data).read(32)
  183. self.assertEqual(res, btv)
  184. def test_ptn_c_1(self):
  185. tv = """FA B6 58 DB 63 E9 4A 24 61 88 BF 7A F6 9A 13 30
  186. 45 F4 6E E9 84 C5 6E 3C 33 28 CA AF 1A A1 A5 83"""
  187. btv = txt2bin(tv)
  188. custom = ptn(1)
  189. # All at once
  190. res = K12.new(custom=custom).read(32)
  191. self.assertEqual(res, btv)
  192. def test_ptn_c_41(self):
  193. tv = """D8 48 C5 06 8C ED 73 6F 44 62 15 9B 98 67 FD 4C
  194. 20 B8 08 AC C3 D5 BC 48 E0 B0 6B A0 A3 76 2E C4"""
  195. btv = txt2bin(tv)
  196. custom = ptn(41)
  197. # All at once
  198. res = K12.new(data=b'\xFF', custom=custom).read(32)
  199. self.assertEqual(res, btv)
  200. def test_ptn_c_41_2(self):
  201. tv = """C3 89 E5 00 9A E5 71 20 85 4C 2E 8C 64 67 0A C0
  202. 13 58 CF 4C 1B AF 89 44 7A 72 42 34 DC 7C ED 74"""
  203. btv = txt2bin(tv)
  204. custom = ptn(41**2)
  205. # All at once
  206. res = K12.new(data=b'\xFF' * 3, custom=custom).read(32)
  207. self.assertEqual(res, btv)
  208. def test_ptn_c_41_3(self):
  209. tv = """75 D2 F8 6A 2E 64 45 66 72 6B 4F BC FC 56 57 B9
  210. DB CF 07 0C 7B 0D CA 06 45 0A B2 91 D7 44 3B CF"""
  211. btv = txt2bin(tv)
  212. custom = ptn(41**3)
  213. # All at once
  214. res = K12.new(data=b'\xFF' * 7, custom=custom).read(32)
  215. self.assertEqual(res, btv)
  216. # https://datatracker.ietf.org/doc/draft-irtf-cfrg-kangarootwelve/
  217. def test_ptn_8191(self):
  218. tv = """1B 57 76 36 F7 23 64 3E 99 0C C7 D6 A6 59 83 74
  219. 36 FD 6A 10 36 26 60 0E B8 30 1C D1 DB E5 53 D6"""
  220. btv = txt2bin(tv)
  221. # All at once
  222. res = K12.new(data=ptn(8191)).read(32)
  223. self.assertEqual(res, btv)
  224. def test_ptn_8192(self):
  225. tv = """48 F2 56 F6 77 2F 9E DF B6 A8 B6 61 EC 92 DC 93
  226. B9 5E BD 05 A0 8A 17 B3 9A E3 49 08 70 C9 26 C3"""
  227. btv = txt2bin(tv)
  228. # All at once
  229. res = K12.new(data=ptn(8192)).read(32)
  230. self.assertEqual(res, btv)
  231. def test_ptn_8192_8189(self):
  232. tv = """3E D1 2F 70 FB 05 DD B5 86 89 51 0A B3 E4 D2 3C
  233. 6C 60 33 84 9A A0 1E 1D 8C 22 0A 29 7F ED CD 0B"""
  234. btv = txt2bin(tv)
  235. # All at once
  236. res = K12.new(data=ptn(8192), custom=ptn(8189)).read(32)
  237. self.assertEqual(res, btv)
  238. def test_ptn_8192_8190(self):
  239. tv = """6A 7C 1B 6A 5C D0 D8 C9 CA 94 3A 4A 21 6C C6 46
  240. 04 55 9A 2E A4 5F 78 57 0A 15 25 3D 67 BA 00 AE"""
  241. btv = txt2bin(tv)
  242. # All at once
  243. res = K12.new(data=ptn(8192), custom=ptn(8190)).read(32)
  244. self.assertEqual(res, btv)
  245. ###
  246. def test_1(self):
  247. tv = "fd608f91d81904a9916e78a18f65c157a78d63f93d8f6367db0524526a5ea2bb"
  248. btv = txt2bin(tv)
  249. res = K12.new(data=b'', custom=ptn(100)).read(32)
  250. self.assertEqual(res, btv)
  251. def test_2(self):
  252. tv4 = "5a4ec9a649f81916d4ce1553492962f7868abf8dd1ceb2f0cb3682ea95cda6a6"
  253. tv3 = "441688fe4fe4ae9425eb3105eb445eb2b3a6f67b66eff8e74ebfbc49371f6d4c"
  254. tv2 = "17269a57759af0214c84a0fd9bc851f4d95f80554cfed4e7da8a6ee1ff080131"
  255. tv1 = "33826990c09dc712ba7224f0d9be319e2720de95a4c1afbd2211507dae1c703a"
  256. tv0 = "9f4d3aba908ddc096e4d3a71da954f917b9752f05052b9d26d916a6fbc75bf3e"
  257. res = K12.new(data=b'A' * (8192 - 4), custom=b'B').read(32)
  258. self.assertEqual(res, txt2bin(tv4))
  259. res = K12.new(data=b'A' * (8192 - 3), custom=b'B').read(32)
  260. self.assertEqual(res, txt2bin(tv3))
  261. res = K12.new(data=b'A' * (8192 - 2), custom=b'B').read(32)
  262. self.assertEqual(res, txt2bin(tv2))
  263. res = K12.new(data=b'A' * (8192 - 1), custom=b'B').read(32)
  264. self.assertEqual(res, txt2bin(tv1))
  265. res = K12.new(data=b'A' * (8192 - 0), custom=b'B').read(32)
  266. self.assertEqual(res, txt2bin(tv0))
  267. def get_tests(config={}):
  268. tests = []
  269. tests += list_test_cases(KangarooTwelveTest)
  270. tests += list_test_cases(KangarooTwelveTV)
  271. return tests
  272. if __name__ == '__main__':
  273. def suite():
  274. return unittest.TestSuite(get_tests())
  275. unittest.main(defaultTest='suite')