test_HMAC.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. # -*- coding: utf-8 -*-
  2. #
  3. # SelfTest/Hash/HMAC.py: Self-test for the HMAC module
  4. #
  5. # Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net>
  6. #
  7. # ===================================================================
  8. # The contents of this file are dedicated to the public domain. To
  9. # the extent that dedication to the public domain is not available,
  10. # everyone is granted a worldwide, perpetual, royalty-free,
  11. # non-exclusive license to exercise all rights associated with the
  12. # contents of this file for any purpose whatsoever.
  13. # No rights are reserved.
  14. #
  15. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  19. # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  20. # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21. # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. # SOFTWARE.
  23. # ===================================================================
  24. """Self-test suite for Crypto.Hash.HMAC"""
  25. import sys
  26. import unittest
  27. from binascii import hexlify
  28. from tls.Crypto.Util.py3compat import _memoryview, tostr, tobytes
  29. from tls.Crypto.Hash import HMAC, MD5, SHA1, SHA256
  30. hash_modules = dict(MD5=MD5, SHA1=SHA1, SHA256=SHA256)
  31. try:
  32. from tls.Crypto.Hash import SHA224, SHA384, SHA512, RIPEMD160
  33. hash_modules.update(dict(SHA224=SHA224, SHA384=SHA384, SHA512=SHA512,
  34. RIPEMD160=RIPEMD160))
  35. except ImportError:
  36. sys.stderr.write("SelfTest: warning: not testing HMAC-SHA224/384/512"
  37. " (not available)\n")
  38. default_hash = None
  39. def xl(text):
  40. return tostr(hexlify(tobytes(text)))
  41. # This is a list of (key, data, results, description) tuples.
  42. test_data = [
  43. ## Test vectors from RFC 2202 ##
  44. # Test that the default hashmod is MD5
  45. ('0b' * 16,
  46. '4869205468657265',
  47. dict(default_hash='9294727a3638bb1c13f48ef8158bfc9d'),
  48. 'default-is-MD5'),
  49. # Test case 1 (MD5)
  50. ('0b' * 16,
  51. '4869205468657265',
  52. dict(MD5='9294727a3638bb1c13f48ef8158bfc9d'),
  53. 'RFC 2202 #1-MD5 (HMAC-MD5)'),
  54. # Test case 1 (SHA1)
  55. ('0b' * 20,
  56. '4869205468657265',
  57. dict(SHA1='b617318655057264e28bc0b6fb378c8ef146be00'),
  58. 'RFC 2202 #1-SHA1 (HMAC-SHA1)'),
  59. # Test case 2
  60. ('4a656665',
  61. '7768617420646f2079612077616e7420666f72206e6f7468696e673f',
  62. dict(MD5='750c783e6ab0b503eaa86e310a5db738',
  63. SHA1='effcdf6ae5eb2fa2d27416d5f184df9c259a7c79'),
  64. 'RFC 2202 #2 (HMAC-MD5/SHA1)'),
  65. # Test case 3 (MD5)
  66. ('aa' * 16,
  67. 'dd' * 50,
  68. dict(MD5='56be34521d144c88dbb8c733f0e8b3f6'),
  69. 'RFC 2202 #3-MD5 (HMAC-MD5)'),
  70. # Test case 3 (SHA1)
  71. ('aa' * 20,
  72. 'dd' * 50,
  73. dict(SHA1='125d7342b9ac11cd91a39af48aa17b4f63f175d3'),
  74. 'RFC 2202 #3-SHA1 (HMAC-SHA1)'),
  75. # Test case 4
  76. ('0102030405060708090a0b0c0d0e0f10111213141516171819',
  77. 'cd' * 50,
  78. dict(MD5='697eaf0aca3a3aea3a75164746ffaa79',
  79. SHA1='4c9007f4026250c6bc8414f9bf50c86c2d7235da'),
  80. 'RFC 2202 #4 (HMAC-MD5/SHA1)'),
  81. # Test case 5 (MD5)
  82. ('0c' * 16,
  83. '546573742057697468205472756e636174696f6e',
  84. dict(MD5='56461ef2342edc00f9bab995690efd4c'),
  85. 'RFC 2202 #5-MD5 (HMAC-MD5)'),
  86. # Test case 5 (SHA1)
  87. # NB: We do not implement hash truncation, so we only test the full hash here.
  88. ('0c' * 20,
  89. '546573742057697468205472756e636174696f6e',
  90. dict(SHA1='4c1a03424b55e07fe7f27be1d58bb9324a9a5a04'),
  91. 'RFC 2202 #5-SHA1 (HMAC-SHA1)'),
  92. # Test case 6
  93. ('aa' * 80,
  94. '54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a'
  95. + '65204b6579202d2048617368204b6579204669727374',
  96. dict(MD5='6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd',
  97. SHA1='aa4ae5e15272d00e95705637ce8a3b55ed402112'),
  98. 'RFC 2202 #6 (HMAC-MD5/SHA1)'),
  99. # Test case 7
  100. ('aa' * 80,
  101. '54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a'
  102. + '65204b657920616e64204c6172676572205468616e204f6e6520426c6f636b2d'
  103. + '53697a652044617461',
  104. dict(MD5='6f630fad67cda0ee1fb1f562db3aa53e',
  105. SHA1='e8e99d0f45237d786d6bbaa7965c7808bbff1a91'),
  106. 'RFC 2202 #7 (HMAC-MD5/SHA1)'),
  107. ## Test vectors from RFC 4231 ##
  108. # 4.2. Test Case 1
  109. ('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b',
  110. '4869205468657265',
  111. dict(SHA256='''
  112. b0344c61d8db38535ca8afceaf0bf12b
  113. 881dc200c9833da726e9376c2e32cff7
  114. '''),
  115. 'RFC 4231 #1 (HMAC-SHA256)'),
  116. # 4.3. Test Case 2 - Test with a key shorter than the length of the HMAC
  117. # output.
  118. ('4a656665',
  119. '7768617420646f2079612077616e7420666f72206e6f7468696e673f',
  120. dict(SHA256='''
  121. 5bdcc146bf60754e6a042426089575c7
  122. 5a003f089d2739839dec58b964ec3843
  123. '''),
  124. 'RFC 4231 #2 (HMAC-SHA256)'),
  125. # 4.4. Test Case 3 - Test with a combined length of key and data that is
  126. # larger than 64 bytes (= block-size of SHA-224 and SHA-256).
  127. ('aa' * 20,
  128. 'dd' * 50,
  129. dict(SHA256='''
  130. 773ea91e36800e46854db8ebd09181a7
  131. 2959098b3ef8c122d9635514ced565fe
  132. '''),
  133. 'RFC 4231 #3 (HMAC-SHA256)'),
  134. # 4.5. Test Case 4 - Test with a combined length of key and data that is
  135. # larger than 64 bytes (= block-size of SHA-224 and SHA-256).
  136. ('0102030405060708090a0b0c0d0e0f10111213141516171819',
  137. 'cd' * 50,
  138. dict(SHA256='''
  139. 82558a389a443c0ea4cc819899f2083a
  140. 85f0faa3e578f8077a2e3ff46729665b
  141. '''),
  142. 'RFC 4231 #4 (HMAC-SHA256)'),
  143. # 4.6. Test Case 5 - Test with a truncation of output to 128 bits.
  144. #
  145. # Not included because we do not implement hash truncation.
  146. #
  147. # 4.7. Test Case 6 - Test with a key larger than 128 bytes (= block-size of
  148. # SHA-384 and SHA-512).
  149. ('aa' * 131,
  150. '54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a'
  151. + '65204b6579202d2048617368204b6579204669727374',
  152. dict(SHA256='''
  153. 60e431591ee0b67f0d8a26aacbf5b77f
  154. 8e0bc6213728c5140546040f0ee37f54
  155. '''),
  156. 'RFC 4231 #6 (HMAC-SHA256)'),
  157. # 4.8. Test Case 7 - Test with a key and data that is larger than 128 bytes
  158. # (= block-size of SHA-384 and SHA-512).
  159. ('aa' * 131,
  160. '5468697320697320612074657374207573696e672061206c6172676572207468'
  161. + '616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074'
  162. + '68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565'
  163. + '647320746f20626520686173686564206265666f7265206265696e6720757365'
  164. + '642062792074686520484d414320616c676f726974686d2e',
  165. dict(SHA256='''
  166. 9b09ffa71b942fcb27635fbcd5b0e944
  167. bfdc63644f0713938a7f51535c3a35e2
  168. '''),
  169. 'RFC 4231 #7 (HMAC-SHA256)'),
  170. # Test case 8 (SHA224)
  171. ('4a656665',
  172. '7768617420646f2079612077616e74'
  173. + '20666f72206e6f7468696e673f',
  174. dict(SHA224='a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44'),
  175. 'RFC 4634 8.4 SHA224 (HMAC-SHA224)'),
  176. # Test case 9 (SHA384)
  177. ('4a656665',
  178. '7768617420646f2079612077616e74'
  179. + '20666f72206e6f7468696e673f',
  180. dict(SHA384='af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649'),
  181. 'RFC 4634 8.4 SHA384 (HMAC-SHA384)'),
  182. # Test case 10 (SHA512)
  183. ('4a656665',
  184. '7768617420646f2079612077616e74'
  185. + '20666f72206e6f7468696e673f',
  186. dict(SHA512='164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737'),
  187. 'RFC 4634 8.4 SHA512 (HMAC-SHA512)'),
  188. # Test case 11 (RIPEMD)
  189. ('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b',
  190. xl("Hi There"),
  191. dict(RIPEMD160='24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668'),
  192. 'RFC 2286 #1 (HMAC-RIPEMD)'),
  193. # Test case 12 (RIPEMD)
  194. (xl("Jefe"),
  195. xl("what do ya want for nothing?"),
  196. dict(RIPEMD160='dda6c0213a485a9e24f4742064a7f033b43c4069'),
  197. 'RFC 2286 #2 (HMAC-RIPEMD)'),
  198. # Test case 13 (RIPEMD)
  199. ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
  200. 'dd' * 50,
  201. dict(RIPEMD160='b0b105360de759960ab4f35298e116e295d8e7c1'),
  202. 'RFC 2286 #3 (HMAC-RIPEMD)'),
  203. # Test case 14 (RIPEMD)
  204. ('0102030405060708090a0b0c0d0e0f10111213141516171819',
  205. 'cd' * 50,
  206. dict(RIPEMD160='d5ca862f4d21d5e610e18b4cf1beb97a4365ecf4'),
  207. 'RFC 2286 #4 (HMAC-RIPEMD)'),
  208. # Test case 15 (RIPEMD)
  209. ('0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c',
  210. xl("Test With Truncation"),
  211. dict(RIPEMD160='7619693978f91d90539ae786500ff3d8e0518e39'),
  212. 'RFC 2286 #5 (HMAC-RIPEMD)'),
  213. # Test case 16 (RIPEMD)
  214. ('aa' * 80,
  215. xl("Test Using Larger Than Block-Size Key - Hash Key First"),
  216. dict(RIPEMD160='6466ca07ac5eac29e1bd523e5ada7605b791fd8b'),
  217. 'RFC 2286 #6 (HMAC-RIPEMD)'),
  218. # Test case 17 (RIPEMD)
  219. ('aa' * 80,
  220. xl("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"),
  221. dict(RIPEMD160='69ea60798d71616cce5fd0871e23754cd75d5a0a'),
  222. 'RFC 2286 #7 (HMAC-RIPEMD)'),
  223. ]
  224. class HMAC_Module_and_Instance_Test(unittest.TestCase):
  225. """Test the HMAC construction and verify that it does not
  226. matter if you initialize it with a hash module or
  227. with an hash instance.
  228. See https://bugs.launchpad.net/pycrypto/+bug/1209399
  229. """
  230. def __init__(self, hashmods):
  231. """Initialize the test with a dictionary of hash modules
  232. indexed by their names"""
  233. unittest.TestCase.__init__(self)
  234. self.hashmods = hashmods
  235. self.description = ""
  236. def shortDescription(self):
  237. return self.description
  238. def runTest(self):
  239. key = b"\x90\x91\x92\x93" * 4
  240. payload = b"\x00" * 100
  241. for hashname, hashmod in self.hashmods.items():
  242. if hashmod is None:
  243. continue
  244. self.description = "Test HMAC in combination with " + hashname
  245. one = HMAC.new(key, payload, hashmod).digest()
  246. two = HMAC.new(key, payload, hashmod.new()).digest()
  247. self.assertEqual(one, two)
  248. class HMAC_None(unittest.TestCase):
  249. def runTest(self):
  250. key = b"\x04" * 20
  251. one = HMAC.new(key, b"", SHA1).digest()
  252. two = HMAC.new(key, None, SHA1).digest()
  253. self.assertEqual(one, two)
  254. class ByteArrayTests(unittest.TestCase):
  255. def runTest(self):
  256. key = b"0" * 16
  257. data = b"\x00\x01\x02"
  258. # Data and key can be a bytearray (during initialization)
  259. key_ba = bytearray(key)
  260. data_ba = bytearray(data)
  261. h1 = HMAC.new(key, data)
  262. h2 = HMAC.new(key_ba, data_ba)
  263. key_ba[:1] = b'\xFF'
  264. data_ba[:1] = b'\xFF'
  265. self.assertEqual(h1.digest(), h2.digest())
  266. # Data can be a bytearray (during operation)
  267. key_ba = bytearray(key)
  268. data_ba = bytearray(data)
  269. h1 = HMAC.new(key)
  270. h2 = HMAC.new(key)
  271. h1.update(data)
  272. h2.update(data_ba)
  273. data_ba[:1] = b'\xFF'
  274. self.assertEqual(h1.digest(), h2.digest())
  275. class MemoryViewTests(unittest.TestCase):
  276. def runTest(self):
  277. key = b"0" * 16
  278. data = b"\x00\x01\x02"
  279. def get_mv_ro(data):
  280. return memoryview(data)
  281. def get_mv_rw(data):
  282. return memoryview(bytearray(data))
  283. for get_mv in (get_mv_ro, get_mv_rw):
  284. # Data and key can be a memoryview (during initialization)
  285. key_mv = get_mv(key)
  286. data_mv = get_mv(data)
  287. h1 = HMAC.new(key, data)
  288. h2 = HMAC.new(key_mv, data_mv)
  289. if not data_mv.readonly:
  290. key_mv[:1] = b'\xFF'
  291. data_mv[:1] = b'\xFF'
  292. self.assertEqual(h1.digest(), h2.digest())
  293. # Data can be a memoryview (during operation)
  294. data_mv = get_mv(data)
  295. h1 = HMAC.new(key)
  296. h2 = HMAC.new(key)
  297. h1.update(data)
  298. h2.update(data_mv)
  299. if not data_mv.readonly:
  300. data_mv[:1] = b'\xFF'
  301. self.assertEqual(h1.digest(), h2.digest())
  302. def get_tests(config={}):
  303. global test_data
  304. import types
  305. from .common import make_mac_tests
  306. # A test vector contains multiple results, each one for a
  307. # different hash algorithm.
  308. # Here we expand each test vector into multiple ones,
  309. # and add the relevant parameters that will be passed to new()
  310. exp_test_data = []
  311. for row in test_data:
  312. for modname in row[2].keys():
  313. t = list(row)
  314. t[2] = row[2][modname]
  315. try:
  316. t.append(dict(digestmod=globals()[modname]))
  317. exp_test_data.append(t)
  318. except AttributeError:
  319. sys.stderr.write("SelfTest: warning: not testing HMAC-%s"
  320. " (not available)\n" % modname)
  321. tests = make_mac_tests(HMAC, "HMAC", exp_test_data)
  322. tests.append(HMAC_Module_and_Instance_Test(hash_modules))
  323. tests.append(HMAC_None())
  324. tests.append(ByteArrayTests())
  325. import sys
  326. if sys.version[:3] != "2.6":
  327. tests.append(MemoryViewTests())
  328. return tests
  329. if __name__ == '__main__':
  330. suite = lambda: unittest.TestSuite(get_tests())
  331. unittest.main(defaultTest='suite')