blob: 890eaba08e8f6fb47978132a28fdb61f7a02b45a [file] [log] [blame]
Guido van Rossum8ceef412001-09-11 15:54:00 +00001"""HMAC (Keyed-Hashing for Message Authentication) Python module.
2
3Implements the HMAC algorithm as described by RFC 2104.
4"""
5
Guido van Rossuma19f80c2007-11-06 20:51:31 +00006import warnings as _warnings
Antoine Pitroua85017f2013-04-20 19:21:44 +02007from _operator import _compare_digest as compare_digest
Christian Heimes2f050c72018-01-27 09:53:43 +01008try:
9 import _hashlib as _hashopenssl
10except ImportError:
11 _hashopenssl = None
12 _openssl_md_meths = None
13else:
14 _openssl_md_meths = frozenset(_hashopenssl.openssl_md_meth_names)
Christian Heimes634919a2013-11-20 17:23:06 +010015import hashlib as _hashlib
Guido van Rossuma19f80c2007-11-06 20:51:31 +000016
Guido van Rossum3f429082007-07-10 13:35:52 +000017trans_5C = bytes((x ^ 0x5C) for x in range(256))
18trans_36 = bytes((x ^ 0x36) for x in range(256))
Tim Petersb64bec32001-09-18 02:26:39 +000019
Andrew M. Kuchling1ccdff92001-11-02 21:49:20 +000020# The size of the digests returned by HMAC depends on the underlying
Thomas Wouters902d6eb2007-01-09 23:18:33 +000021# hashing module used. Use digest_size from the instance of HMAC instead.
Andrew M. Kuchling1ccdff92001-11-02 21:49:20 +000022digest_size = None
23
Tim Peters934d31b2004-03-20 20:11:29 +000024
Charles-François Natali7feb9f42012-05-13 19:53:07 +020025
Guido van Rossum8ceef412001-09-11 15:54:00 +000026class HMAC:
Guido van Rossuma19f80c2007-11-06 20:51:31 +000027 """RFC 2104 HMAC class. Also complies with RFC 4231.
Guido van Rossum8ceef412001-09-11 15:54:00 +000028
Andrew M. Kuchling1ccdff92001-11-02 21:49:20 +000029 This supports the API for Cryptographic Hash Functions (PEP 247).
Tim Petersb64bec32001-09-18 02:26:39 +000030 """
Thomas Wouters902d6eb2007-01-09 23:18:33 +000031 blocksize = 64 # 512-bit HMAC; can be changed in subclasses.
Guido van Rossum8ceef412001-09-11 15:54:00 +000032
33 def __init__(self, key, msg = None, digestmod = None):
34 """Create a new HMAC object.
35
36 key: key for the keyed hash object.
37 msg: Initial input for the hash, if provided.
Matthias Bussonnier51a47432018-09-10 20:10:01 +020038 digestmod: Required. A module supporting PEP 247. *OR*
39 A hashlib constructor returning a new hash object. *OR*
Christian Heimes634919a2013-11-20 17:23:06 +010040 A hash name suitable for hashlib.new().
Guido van Rossum3f429082007-07-10 13:35:52 +000041
Christian Heimes04926ae2013-07-01 13:08:42 +020042 Note: key and msg must be a bytes or bytearray objects.
Guido van Rossum8ceef412001-09-11 15:54:00 +000043 """
Tim Peters934d31b2004-03-20 20:11:29 +000044
Christian Heimes04926ae2013-07-01 13:08:42 +020045 if not isinstance(key, (bytes, bytearray)):
46 raise TypeError("key: expected bytes or bytearray, but got %r" % type(key).__name__)
Guido van Rossum3f429082007-07-10 13:35:52 +000047
Raymond Hettinger7fdfc2d2002-05-31 17:49:10 +000048 if digestmod is None:
Matthias Bussonnier51a47432018-09-10 20:10:01 +020049 raise ValueError('`digestmod` is required.')
Guido van Rossum8ceef412001-09-11 15:54:00 +000050
Florent Xicluna5d1155c2011-10-28 14:45:05 +020051 if callable(digestmod):
Gregory P. Smithf21a5f72005-08-21 18:45:59 +000052 self.digest_cons = digestmod
Christian Heimes634919a2013-11-20 17:23:06 +010053 elif isinstance(digestmod, str):
54 self.digest_cons = lambda d=b'': _hashlib.new(digestmod, d)
Gregory P. Smithf21a5f72005-08-21 18:45:59 +000055 else:
Guido van Rossum3f429082007-07-10 13:35:52 +000056 self.digest_cons = lambda d=b'': digestmod.new(d)
Gregory P. Smithf21a5f72005-08-21 18:45:59 +000057
58 self.outer = self.digest_cons()
59 self.inner = self.digest_cons()
60 self.digest_size = self.inner.digest_size
Tim Peters88768482001-11-13 21:51:26 +000061
Guido van Rossuma19f80c2007-11-06 20:51:31 +000062 if hasattr(self.inner, 'block_size'):
63 blocksize = self.inner.block_size
64 if blocksize < 16:
Guido van Rossuma19f80c2007-11-06 20:51:31 +000065 _warnings.warn('block_size of %d seems too small; using our '
66 'default of %d.' % (blocksize, self.blocksize),
67 RuntimeWarning, 2)
68 blocksize = self.blocksize
69 else:
70 _warnings.warn('No block_size attribute on given digest object; '
71 'Assuming %d.' % (self.blocksize),
72 RuntimeWarning, 2)
73 blocksize = self.blocksize
74
Christian Heimesc4ab1102013-11-20 17:35:06 +010075 # self.blocksize is the default blocksize. self.block_size is
76 # effective block size as well as the public API attribute.
77 self.block_size = blocksize
78
Guido van Rossum8ceef412001-09-11 15:54:00 +000079 if len(key) > blocksize:
Gregory P. Smithf21a5f72005-08-21 18:45:59 +000080 key = self.digest_cons(key).digest()
Guido van Rossum8ceef412001-09-11 15:54:00 +000081
Serhiy Storchaka5f1a5182016-09-11 14:41:02 +030082 key = key.ljust(blocksize, b'\0')
Thomas Wouters902d6eb2007-01-09 23:18:33 +000083 self.outer.update(key.translate(trans_5C))
84 self.inner.update(key.translate(trans_36))
Raymond Hettinger094662a2002-06-01 01:29:16 +000085 if msg is not None:
Guido van Rossum8ceef412001-09-11 15:54:00 +000086 self.update(msg)
87
Christian Heimesc4ab1102013-11-20 17:35:06 +010088 @property
89 def name(self):
90 return "hmac-" + self.inner.name
91
Guido van Rossum8ceef412001-09-11 15:54:00 +000092 def update(self, msg):
93 """Update this hashing object with the string msg.
94 """
95 self.inner.update(msg)
96
97 def copy(self):
98 """Return a separate copy of this hashing object.
99
100 An update to this copy won't affect the original object.
101 """
Benjamin Peterson0cc74442010-08-21 02:45:15 +0000102 # Call __new__ directly to avoid the expensive __init__.
103 other = self.__class__.__new__(self.__class__)
Gregory P. Smithf21a5f72005-08-21 18:45:59 +0000104 other.digest_cons = self.digest_cons
Tim Peters934d31b2004-03-20 20:11:29 +0000105 other.digest_size = self.digest_size
Andrew M. Kuchling1ccdff92001-11-02 21:49:20 +0000106 other.inner = self.inner.copy()
107 other.outer = self.outer.copy()
108 return other
Guido van Rossum8ceef412001-09-11 15:54:00 +0000109
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000110 def _current(self):
111 """Return a hash object for the current state.
112
113 To be used only internally with digest() and hexdigest().
114 """
115 h = self.outer.copy()
116 h.update(self.inner.digest())
117 return h
118
Guido van Rossum8ceef412001-09-11 15:54:00 +0000119 def digest(self):
120 """Return the hash value of this hashing object.
121
122 This returns a string containing 8-bit data. The object is
123 not altered in any way by this function; you can continue
124 updating the object after calling this function.
125 """
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000126 h = self._current()
Guido van Rossum8ceef412001-09-11 15:54:00 +0000127 return h.digest()
128
129 def hexdigest(self):
130 """Like digest(), but returns a string of hexadecimal digits instead.
131 """
Thomas Wouters902d6eb2007-01-09 23:18:33 +0000132 h = self._current()
133 return h.hexdigest()
Guido van Rossum8ceef412001-09-11 15:54:00 +0000134
135def new(key, msg = None, digestmod = None):
136 """Create a new hashing object and return it.
137
138 key: The starting key for the hash.
139 msg: if available, will immediately be hashed into the object's starting
Tim Petersb64bec32001-09-18 02:26:39 +0000140 state.
Guido van Rossum8ceef412001-09-11 15:54:00 +0000141
142 You can now feed arbitrary strings into the object using its update()
143 method, and can ask for the hash value at any time by calling its digest()
144 method.
145 """
146 return HMAC(key, msg, digestmod)
Christian Heimes2f050c72018-01-27 09:53:43 +0100147
148
149def digest(key, msg, digest):
150 """Fast inline implementation of HMAC
151
152 key: key for the keyed hash object.
153 msg: input message
154 digest: A hash name suitable for hashlib.new() for best performance. *OR*
155 A hashlib constructor returning a new hash object. *OR*
156 A module supporting PEP 247.
157
158 Note: key and msg must be a bytes or bytearray objects.
159 """
160 if (_hashopenssl is not None and
161 isinstance(digest, str) and digest in _openssl_md_meths):
162 return _hashopenssl.hmac_digest(key, msg, digest)
163
164 if callable(digest):
165 digest_cons = digest
166 elif isinstance(digest, str):
167 digest_cons = lambda d=b'': _hashlib.new(digest, d)
168 else:
169 digest_cons = lambda d=b'': digest.new(d)
170
171 inner = digest_cons()
172 outer = digest_cons()
173 blocksize = getattr(inner, 'block_size', 64)
174 if len(key) > blocksize:
175 key = digest_cons(key).digest()
176 key = key + b'\x00' * (blocksize - len(key))
177 inner.update(key.translate(trans_36))
178 outer.update(key.translate(trans_5C))
179 inner.update(msg)
180 outer.update(inner.digest())
181 return outer.digest()