HMAC.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. # HMAC.py - Implements the HMAC algorithm as described by RFC 2104.
  2. #
  3. # ===================================================================
  4. # Portions Copyright (c) 2001, 2002, 2003 Python Software Foundation;
  5. # All Rights Reserved
  6. #
  7. # This file contains code from the Python 2.2 hmac.py module (the
  8. # "Original Code"), with modifications made after it was incorporated
  9. # into PyCrypto (the "Modifications").
  10. #
  11. # To the best of our knowledge, the Python Software Foundation is the
  12. # copyright holder of the Original Code, and has licensed it under the
  13. # Python 2.2 license. See the file LEGAL/copy/LICENSE.python-2.2 for
  14. # details.
  15. #
  16. # The Modifications to this file are dedicated to the public domain.
  17. # To the extent that dedication to the public domain is not available,
  18. # everyone is granted a worldwide, perpetual, royalty-free,
  19. # non-exclusive license to exercise all rights associated with the
  20. # contents of this file for any purpose whatsoever. No rights are
  21. # reserved.
  22. #
  23. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  27. # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  28. # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  29. # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  30. # SOFTWARE.
  31. # ===================================================================
  32. """HMAC (Hash-based Message Authentication Code) algorithm
  33. HMAC is a MAC defined in RFC2104_ and FIPS-198_ and constructed using
  34. a cryptograpic hash algorithm.
  35. It is usually named *HMAC-X*, where *X* is the hash algorithm; for
  36. instance *HMAC-SHA1* or *HMAC-MD5*.
  37. The strength of an HMAC depends on:
  38. - the strength of the hash algorithm
  39. - the length and entropy of the secret key
  40. An example of possible usage is the following:
  41. >>> from Crypto.Hash import HMAC
  42. >>>
  43. >>> secret = b'Swordfish'
  44. >>> h = HMAC.new(secret)
  45. >>> h.update(b'Hello')
  46. >>> print h.hexdigest()
  47. .. _RFC2104: http://www.ietf.org/rfc/rfc2104.txt
  48. .. _FIPS-198: http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf
  49. """
  50. # This is just a copy of the Python 2.2 HMAC module, modified to work when
  51. # used on versions of Python before 2.2.
  52. __revision__ = "$Id$"
  53. __all__ = ['new', 'digest_size', 'HMAC' ]
  54. from Crypto.Util.strxor import strxor_c
  55. from Crypto.Util.py3compat import *
  56. #: The size of the authentication tag produced by the MAC.
  57. #: It matches the digest size on the underlying
  58. #: hashing module used.
  59. digest_size = None
  60. class HMAC:
  61. """Class that implements HMAC"""
  62. #: The size of the authentication tag produced by the MAC.
  63. #: It matches the digest size on the underlying
  64. #: hashing module used.
  65. digest_size = None
  66. def __init__(self, key, msg = None, digestmod = None):
  67. """Create a new HMAC object.
  68. :Parameters:
  69. key : byte string
  70. secret key for the MAC object.
  71. It must be long enough to match the expected security level of the
  72. MAC. However, there is no benefit in using keys longer than the
  73. `digest_size` of the underlying hash algorithm.
  74. msg : byte string
  75. The very first chunk of the message to authenticate.
  76. It is equivalent to an early call to `update()`. Optional.
  77. :Parameter digestmod:
  78. The hash algorithm the HMAC is based on.
  79. Default is `Crypto.Hash.MD5`.
  80. :Type digestmod:
  81. A hash module or object instantiated from `Crypto.Hash`
  82. """
  83. if digestmod is None:
  84. import MD5
  85. digestmod = MD5
  86. self.digestmod = digestmod
  87. self.outer = digestmod.new()
  88. self.inner = digestmod.new()
  89. try:
  90. self.digest_size = digestmod.digest_size
  91. except AttributeError:
  92. self.digest_size = len(self.outer.digest())
  93. try:
  94. # The block size is 128 bytes for SHA384 and SHA512 and 64 bytes
  95. # for the others hash function
  96. blocksize = digestmod.block_size
  97. except AttributeError:
  98. blocksize = 64
  99. ipad = 0x36
  100. opad = 0x5C
  101. if len(key) > blocksize:
  102. key = digestmod.new(key).digest()
  103. key = key + bchr(0) * (blocksize - len(key))
  104. self.outer.update(strxor_c(key, opad))
  105. self.inner.update(strxor_c(key, ipad))
  106. if (msg):
  107. self.update(msg)
  108. def update(self, msg):
  109. """Continue authentication of a message by consuming the next chunk of data.
  110. Repeated calls are equivalent to a single call with the concatenation
  111. of all the arguments. In other words:
  112. >>> m.update(a); m.update(b)
  113. is equivalent to:
  114. >>> m.update(a+b)
  115. :Parameters:
  116. msg : byte string
  117. The next chunk of the message being authenticated
  118. """
  119. self.inner.update(msg)
  120. def copy(self):
  121. """Return a copy ("clone") of the MAC object.
  122. The copy will have the same internal state as the original MAC
  123. object.
  124. This can be used to efficiently compute the MAC of strings that
  125. share a common initial substring.
  126. :Returns: An `HMAC` object
  127. """
  128. other = HMAC(b(""))
  129. other.digestmod = self.digestmod
  130. other.inner = self.inner.copy()
  131. other.outer = self.outer.copy()
  132. return other
  133. def digest(self):
  134. """Return the **binary** (non-printable) MAC of the message that has
  135. been authenticated so far.
  136. This method does not change the state of the MAC object.
  137. You can continue updating the object after calling this function.
  138. :Return: A byte string of `digest_size` bytes. It may contain non-ASCII
  139. characters, including null bytes.
  140. """
  141. h = self.outer.copy()
  142. h.update(self.inner.digest())
  143. return h.digest()
  144. def hexdigest(self):
  145. """Return the **printable** MAC of the message that has been
  146. authenticated so far.
  147. This method does not change the state of the MAC object.
  148. :Return: A string of 2* `digest_size` bytes. It contains only
  149. hexadecimal ASCII digits.
  150. """
  151. return "".join(["%02x" % bord(x)
  152. for x in tuple(self.digest())])
  153. def new(key, msg = None, digestmod = None):
  154. """Create a new HMAC object.
  155. :Parameters:
  156. key : byte string
  157. key for the MAC object.
  158. It must be long enough to match the expected security level of the
  159. MAC. However, there is no benefit in using keys longer than the
  160. `digest_size` of the underlying hash algorithm.
  161. msg : byte string
  162. The very first chunk of the message to authenticate.
  163. It is equivalent to an early call to `HMAC.update()`.
  164. Optional.
  165. :Parameter digestmod:
  166. The hash to use to implement the HMAC. Default is `Crypto.Hash.MD5`.
  167. :Type digestmod:
  168. A hash module or instantiated object from `Crypto.Hash`
  169. :Returns: An `HMAC` object
  170. """
  171. return HMAC(key, msg, digestmod)