test_keccak.py 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. # ===================================================================
  2. #
  3. # Copyright (c) 2015, Legrandin <helderijs@gmail.com>
  4. # All rights reserved.
  5. #
  6. # Redistribution and use in source and binary forms, with or without
  7. # modification, are permitted provided that the following conditions
  8. # are met:
  9. #
  10. # 1. Redistributions of source code must retain the above copyright
  11. # notice, this list of conditions and the following disclaimer.
  12. # 2. Redistributions in binary form must reproduce the above copyright
  13. # notice, this list of conditions and the following disclaimer in
  14. # the documentation and/or other materials provided with the
  15. # distribution.
  16. #
  17. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  25. # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  27. # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. # POSSIBILITY OF SUCH DAMAGE.
  29. # ===================================================================
  30. """Self-test suite for Crypto.Hash.keccak"""
  31. import unittest
  32. from binascii import hexlify, unhexlify
  33. from tls.Crypto.SelfTest.loader import load_tests
  34. from tls.Crypto.SelfTest.st_common import list_test_cases
  35. from tls.Crypto.Hash import keccak
  36. from tls.Crypto.Util.py3compat import b, tobytes, bchr
  37. class KeccakTest(unittest.TestCase):
  38. def test_new_positive(self):
  39. for digest_bits in (224, 256, 384, 512):
  40. hobj = keccak.new(digest_bits=digest_bits)
  41. self.assertEqual(hobj.digest_size, digest_bits // 8)
  42. hobj2 = hobj.new()
  43. self.assertEqual(hobj2.digest_size, digest_bits // 8)
  44. for digest_bytes in (28, 32, 48, 64):
  45. hobj = keccak.new(digest_bytes=digest_bytes)
  46. self.assertEqual(hobj.digest_size, digest_bytes)
  47. hobj2 = hobj.new()
  48. self.assertEqual(hobj2.digest_size, digest_bytes)
  49. def test_new_positive2(self):
  50. digest1 = keccak.new(data=b("\x90"), digest_bytes=64).digest()
  51. digest2 = keccak.new(digest_bytes=64).update(b("\x90")).digest()
  52. self.assertEqual(digest1, digest2)
  53. def test_new_negative(self):
  54. # keccak.new needs digest size
  55. self.assertRaises(TypeError, keccak.new)
  56. h = keccak.new(digest_bits=512)
  57. # Either bits or bytes can be specified
  58. self.assertRaises(TypeError, keccak.new,
  59. digest_bytes=64,
  60. digest_bits=512)
  61. # Range
  62. self.assertRaises(ValueError, keccak.new, digest_bytes=0)
  63. self.assertRaises(ValueError, keccak.new, digest_bytes=1)
  64. self.assertRaises(ValueError, keccak.new, digest_bytes=65)
  65. self.assertRaises(ValueError, keccak.new, digest_bits=0)
  66. self.assertRaises(ValueError, keccak.new, digest_bits=1)
  67. self.assertRaises(ValueError, keccak.new, digest_bits=513)
  68. def test_update(self):
  69. pieces = [bchr(10) * 200, bchr(20) * 300]
  70. h = keccak.new(digest_bytes=64)
  71. h.update(pieces[0]).update(pieces[1])
  72. digest = h.digest()
  73. h = keccak.new(digest_bytes=64)
  74. h.update(pieces[0] + pieces[1])
  75. self.assertEqual(h.digest(), digest)
  76. def test_update_negative(self):
  77. h = keccak.new(digest_bytes=64)
  78. self.assertRaises(TypeError, h.update, u"string")
  79. def test_digest(self):
  80. h = keccak.new(digest_bytes=64)
  81. digest = h.digest()
  82. # hexdigest does not change the state
  83. self.assertEqual(h.digest(), digest)
  84. # digest returns a byte string
  85. self.failUnless(isinstance(digest, type(b("digest"))))
  86. def test_hex_digest(self):
  87. mac = keccak.new(digest_bits=512)
  88. digest = mac.digest()
  89. hexdigest = mac.hexdigest()
  90. # hexdigest is equivalent to digest
  91. self.assertEqual(hexlify(digest), tobytes(hexdigest))
  92. # hexdigest does not change the state
  93. self.assertEqual(mac.hexdigest(), hexdigest)
  94. # hexdigest returns a string
  95. self.failUnless(isinstance(hexdigest, type("digest")))
  96. def test_update_after_digest(self):
  97. msg=b("rrrrttt")
  98. # Normally, update() cannot be done after digest()
  99. h = keccak.new(digest_bits=512, data=msg[:4])
  100. dig1 = h.digest()
  101. self.assertRaises(TypeError, h.update, msg[4:])
  102. dig2 = keccak.new(digest_bits=512, data=msg).digest()
  103. # With the proper flag, it is allowed
  104. h = keccak.new(digest_bits=512, data=msg[:4], update_after_digest=True)
  105. self.assertEquals(h.digest(), dig1)
  106. # ... and the subsequent digest applies to the entire message
  107. # up to that point
  108. h.update(msg[4:])
  109. self.assertEquals(h.digest(), dig2)
  110. class KeccakVectors(unittest.TestCase):
  111. pass
  112. # TODO: add ExtremelyLong tests
  113. test_vectors_224 = load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "keccak"),
  114. "ShortMsgKAT_224.txt",
  115. "Short Messages KAT 224",
  116. { "len" : lambda x: int(x) } )
  117. test_vectors_224 += load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "keccak"),
  118. "LongMsgKAT_224.txt",
  119. "Long Messages KAT 224",
  120. { "len" : lambda x: int(x) } )
  121. for idx, tv in enumerate(test_vectors_224):
  122. if tv.len == 0:
  123. data = b("")
  124. else:
  125. data = tobytes(tv.msg)
  126. def new_test(self, data=data, result=tv.md):
  127. hobj = keccak.new(digest_bits=224, data=data)
  128. self.assertEqual(hobj.digest(), result)
  129. setattr(KeccakVectors, "test_224_%d" % idx, new_test)
  130. # ---
  131. test_vectors_256 = load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "keccak"),
  132. "ShortMsgKAT_256.txt",
  133. "Short Messages KAT 256",
  134. { "len" : lambda x: int(x) } )
  135. test_vectors_256 += load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "keccak"),
  136. "LongMsgKAT_256.txt",
  137. "Long Messages KAT 256",
  138. { "len" : lambda x: int(x) } )
  139. for idx, tv in enumerate(test_vectors_256):
  140. if tv.len == 0:
  141. data = b("")
  142. else:
  143. data = tobytes(tv.msg)
  144. def new_test(self, data=data, result=tv.md):
  145. hobj = keccak.new(digest_bits=256, data=data)
  146. self.assertEqual(hobj.digest(), result)
  147. setattr(KeccakVectors, "test_256_%d" % idx, new_test)
  148. # ---
  149. test_vectors_384 = load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "keccak"),
  150. "ShortMsgKAT_384.txt",
  151. "Short Messages KAT 384",
  152. { "len" : lambda x: int(x) } )
  153. test_vectors_384 += load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "keccak"),
  154. "LongMsgKAT_384.txt",
  155. "Long Messages KAT 384",
  156. { "len" : lambda x: int(x) } )
  157. for idx, tv in enumerate(test_vectors_384):
  158. if tv.len == 0:
  159. data = b("")
  160. else:
  161. data = tobytes(tv.msg)
  162. def new_test(self, data=data, result=tv.md):
  163. hobj = keccak.new(digest_bits=384, data=data)
  164. self.assertEqual(hobj.digest(), result)
  165. setattr(KeccakVectors, "test_384_%d" % idx, new_test)
  166. # ---
  167. test_vectors_512 = load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "keccak"),
  168. "ShortMsgKAT_512.txt",
  169. "Short Messages KAT 512",
  170. { "len" : lambda x: int(x) } )
  171. test_vectors_512 += load_tests(("Crypto", "SelfTest", "Hash", "test_vectors", "keccak"),
  172. "LongMsgKAT_512.txt",
  173. "Long Messages KAT 512",
  174. { "len" : lambda x: int(x) } )
  175. for idx, tv in enumerate(test_vectors_512):
  176. if tv.len == 0:
  177. data = b("")
  178. else:
  179. data = tobytes(tv.msg)
  180. def new_test(self, data=data, result=tv.md):
  181. hobj = keccak.new(digest_bits=512, data=data)
  182. self.assertEqual(hobj.digest(), result)
  183. setattr(KeccakVectors, "test_512_%d" % idx, new_test)
  184. def get_tests(config={}):
  185. tests = []
  186. tests += list_test_cases(KeccakTest)
  187. tests += list_test_cases(KeccakVectors)
  188. return tests
  189. if __name__ == '__main__':
  190. import unittest
  191. suite = lambda: unittest.TestSuite(get_tests())
  192. unittest.main(defaultTest='suite')