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