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 33 34"""HMAC (Hash-based Message Authentication Code) algorithm 35 36HMAC is a MAC defined in RFC2104_ and FIPS-198_ and constructed using 37a cryptograpic hash algorithm. 38It is usually named *HMAC-X*, where *X* is the hash algorithm; for 39instance *HMAC-SHA1* or *HMAC-MD5*. 40 41The strength of an HMAC depends on: 42 43 - the strength of the hash algorithm 44 - the length and entropy of the secret key 45 46An example of possible usage is the following: 47 48 >>> from Crypto.Hash import HMAC 49 >>> 50 >>> secret = b'Swordfish' 51 >>> h = HMAC.new(secret) 52 >>> h.update(b'Hello') 53 >>> print h.hexdigest() 54 55.. _RFC2104: http://www.ietf.org/rfc/rfc2104.txt 56.. _FIPS-198: http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf 57""" 58 59# This is just a copy of the Python 2.2 HMAC module, modified to work when 60# used on versions of Python before 2.2. 61 62__revision__ = "$Id$" 63 64__all__ = ['new', 'digest_size', 'HMAC' ] 65 66from Crypto.Util.strxor import strxor_c 67from Crypto.Util.py3compat import * 68 69#: The size of the authentication tag produced by the MAC. 70#: It matches the digest size on the underlying 71#: hashing module used. 72digest_size = None 73 74class HMAC: 75 """Class that implements HMAC""" 76 77 #: The size of the authentication tag produced by the MAC. 78 #: It matches the digest size on the underlying 79 #: hashing module used. 80 digest_size = None 81 82 def __init__(self, key, msg = None, digestmod = None): 83 """Create a new HMAC object. 84 85 :Parameters: 86 key : byte string 87 secret key for the MAC object. 88 It must be long enough to match the expected security level of the 89 MAC. However, there is no benefit in using keys longer than the 90 `digest_size` of the underlying hash algorithm. 91 msg : byte string 92 The very first chunk of the message to authenticate. 93 It is equivalent to an early call to `update()`. Optional. 94 :Parameter digestmod: 95 The hash algorithm the HMAC is based on. 96 Default is `Crypto.Hash.MD5`. 97 :Type digestmod: 98 A hash module or object instantiated from `Crypto.Hash` 99 """ 100 if digestmod is None: 101 import MD5 102 digestmod = MD5 103 104 self.digestmod = digestmod 105 self.outer = digestmod.new() 106 self.inner = digestmod.new() 107 try: 108 self.digest_size = digestmod.digest_size 109 except AttributeError: 110 self.digest_size = len(self.outer.digest()) 111 112 try: 113 # The block size is 128 bytes for SHA384 and SHA512 and 64 bytes 114 # for the others hash function 115 blocksize = digestmod.block_size 116 except AttributeError: 117 blocksize = 64 118 119 ipad = 0x36 120 opad = 0x5C 121 122 if len(key) > blocksize: 123 key = digestmod.new(key).digest() 124 125 key = key + bchr(0) * (blocksize - len(key)) 126 self.outer.update(strxor_c(key, opad)) 127 self.inner.update(strxor_c(key, ipad)) 128 if (msg): 129 self.update(msg) 130 131 def update(self, msg): 132 """Continue authentication of a message by consuming the next chunk of data. 133 134 Repeated calls are equivalent to a single call with the concatenation 135 of all the arguments. In other words: 136 137 >>> m.update(a); m.update(b) 138 139 is equivalent to: 140 141 >>> m.update(a+b) 142 143 :Parameters: 144 msg : byte string 145 The next chunk of the message being authenticated 146 """ 147 148 self.inner.update(msg) 149 150 def copy(self): 151 """Return a copy ("clone") of the MAC object. 152 153 The copy will have the same internal state as the original MAC 154 object. 155 This can be used to efficiently compute the MAC of strings that 156 share a common initial substring. 157 158 :Returns: An `HMAC` object 159 """ 160 other = HMAC(b("")) 161 other.digestmod = self.digestmod 162 other.inner = self.inner.copy() 163 other.outer = self.outer.copy() 164 return other 165 166 def digest(self): 167 """Return the **binary** (non-printable) MAC of the message that has 168 been authenticated so far. 169 170 This method does not change the state of the MAC object. 171 You can continue updating the object after calling this function. 172 173 :Return: A byte string of `digest_size` bytes. It may contain non-ASCII 174 characters, including null bytes. 175 """ 176 h = self.outer.copy() 177 h.update(self.inner.digest()) 178 return h.digest() 179 180 def hexdigest(self): 181 """Return the **printable** MAC of the message that has been 182 authenticated so far. 183 184 This method does not change the state of the MAC object. 185 186 :Return: A string of 2* `digest_size` bytes. It contains only 187 hexadecimal ASCII digits. 188 """ 189 return "".join(["%02x" % bord(x) 190 for x in tuple(self.digest())]) 191 192def new(key, msg = None, digestmod = None): 193 """Create a new HMAC object. 194 195 :Parameters: 196 key : byte string 197 key for the MAC object. 198 It must be long enough to match the expected security level of the 199 MAC. However, there is no benefit in using keys longer than the 200 `digest_size` of the underlying hash algorithm. 201 msg : byte string 202 The very first chunk of the message to authenticate. 203 It is equivalent to an early call to `HMAC.update()`. 204 Optional. 205 :Parameter digestmod: 206 The hash to use to implement the HMAC. Default is `Crypto.Hash.MD5`. 207 :Type digestmod: 208 A hash module or instantiated object from `Crypto.Hash` 209 :Returns: An `HMAC` object 210 """ 211 return HMAC(key, msg, digestmod) 212 213