| """HMAC (Keyed-Hashing for Message Authentication) module. | 
 |  | 
 | Implements the HMAC algorithm as described by RFC 2104. | 
 | """ | 
 |  | 
 | import warnings as _warnings | 
 | from _operator import _compare_digest as compare_digest | 
 | try: | 
 |     import _hashlib as _hashopenssl | 
 | except ImportError: | 
 |     _hashopenssl = None | 
 |     _openssl_md_meths = None | 
 | else: | 
 |     _openssl_md_meths = frozenset(_hashopenssl.openssl_md_meth_names) | 
 | import hashlib as _hashlib | 
 |  | 
 | trans_5C = bytes((x ^ 0x5C) for x in range(256)) | 
 | trans_36 = bytes((x ^ 0x36) for x in range(256)) | 
 |  | 
 | # The size of the digests returned by HMAC depends on the underlying | 
 | # hashing module used.  Use digest_size from the instance of HMAC instead. | 
 | digest_size = None | 
 |  | 
 |  | 
 |  | 
 | class HMAC: | 
 |     """RFC 2104 HMAC class.  Also complies with RFC 4231. | 
 |  | 
 |     This supports the API for Cryptographic Hash Functions (PEP 247). | 
 |     """ | 
 |     blocksize = 64  # 512-bit HMAC; can be changed in subclasses. | 
 |  | 
 |     def __init__(self, key, msg=None, digestmod=''): | 
 |         """Create a new HMAC object. | 
 |  | 
 |         key: bytes or buffer, key for the keyed hash object. | 
 |         msg: bytes or buffer, Initial input for the hash or None. | 
 |         digestmod: A hash name suitable for hashlib.new(). *OR* | 
 |                    A hashlib constructor returning a new hash object. *OR* | 
 |                    A module supporting PEP 247. | 
 |  | 
 |                    Required as of 3.8, despite its position after the optional | 
 |                    msg argument.  Passing it as a keyword argument is | 
 |                    recommended, though not required for legacy API reasons. | 
 |         """ | 
 |  | 
 |         if not isinstance(key, (bytes, bytearray)): | 
 |             raise TypeError("key: expected bytes or bytearray, but got %r" % type(key).__name__) | 
 |  | 
 |         if not digestmod: | 
 |             raise TypeError("Missing required parameter 'digestmod'.") | 
 |  | 
 |         if callable(digestmod): | 
 |             self.digest_cons = digestmod | 
 |         elif isinstance(digestmod, str): | 
 |             self.digest_cons = lambda d=b'': _hashlib.new(digestmod, d) | 
 |         else: | 
 |             self.digest_cons = lambda d=b'': digestmod.new(d) | 
 |  | 
 |         self.outer = self.digest_cons() | 
 |         self.inner = self.digest_cons() | 
 |         self.digest_size = self.inner.digest_size | 
 |  | 
 |         if hasattr(self.inner, 'block_size'): | 
 |             blocksize = self.inner.block_size | 
 |             if blocksize < 16: | 
 |                 _warnings.warn('block_size of %d seems too small; using our ' | 
 |                                'default of %d.' % (blocksize, self.blocksize), | 
 |                                RuntimeWarning, 2) | 
 |                 blocksize = self.blocksize | 
 |         else: | 
 |             _warnings.warn('No block_size attribute on given digest object; ' | 
 |                            'Assuming %d.' % (self.blocksize), | 
 |                            RuntimeWarning, 2) | 
 |             blocksize = self.blocksize | 
 |  | 
 |         # self.blocksize is the default blocksize. self.block_size is | 
 |         # effective block size as well as the public API attribute. | 
 |         self.block_size = blocksize | 
 |  | 
 |         if len(key) > blocksize: | 
 |             key = self.digest_cons(key).digest() | 
 |  | 
 |         key = key.ljust(blocksize, b'\0') | 
 |         self.outer.update(key.translate(trans_5C)) | 
 |         self.inner.update(key.translate(trans_36)) | 
 |         if msg is not None: | 
 |             self.update(msg) | 
 |  | 
 |     @property | 
 |     def name(self): | 
 |         return "hmac-" + self.inner.name | 
 |  | 
 |     def update(self, msg): | 
 |         """Feed data from msg into this hashing object.""" | 
 |         self.inner.update(msg) | 
 |  | 
 |     def copy(self): | 
 |         """Return a separate copy of this hashing object. | 
 |  | 
 |         An update to this copy won't affect the original object. | 
 |         """ | 
 |         # Call __new__ directly to avoid the expensive __init__. | 
 |         other = self.__class__.__new__(self.__class__) | 
 |         other.digest_cons = self.digest_cons | 
 |         other.digest_size = self.digest_size | 
 |         other.inner = self.inner.copy() | 
 |         other.outer = self.outer.copy() | 
 |         return other | 
 |  | 
 |     def _current(self): | 
 |         """Return a hash object for the current state. | 
 |  | 
 |         To be used only internally with digest() and hexdigest(). | 
 |         """ | 
 |         h = self.outer.copy() | 
 |         h.update(self.inner.digest()) | 
 |         return h | 
 |  | 
 |     def digest(self): | 
 |         """Return the hash value of this hashing object. | 
 |  | 
 |         This returns the hmac value as bytes.  The object is | 
 |         not altered in any way by this function; you can continue | 
 |         updating the object after calling this function. | 
 |         """ | 
 |         h = self._current() | 
 |         return h.digest() | 
 |  | 
 |     def hexdigest(self): | 
 |         """Like digest(), but returns a string of hexadecimal digits instead. | 
 |         """ | 
 |         h = self._current() | 
 |         return h.hexdigest() | 
 |  | 
 | def new(key, msg=None, digestmod=''): | 
 |     """Create a new hashing object and return it. | 
 |  | 
 |     key: bytes or buffer, The starting key for the hash. | 
 |     msg: bytes or buffer, Initial input for the hash, or None. | 
 |     digestmod: A hash name suitable for hashlib.new(). *OR* | 
 |                A hashlib constructor returning a new hash object. *OR* | 
 |                A module supporting PEP 247. | 
 |  | 
 |                Required as of 3.8, despite its position after the optional | 
 |                msg argument.  Passing it as a keyword argument is | 
 |                recommended, though not required for legacy API reasons. | 
 |  | 
 |     You can now feed arbitrary bytes into the object using its update() | 
 |     method, and can ask for the hash value at any time by calling its digest() | 
 |     or hexdigest() methods. | 
 |     """ | 
 |     return HMAC(key, msg, digestmod) | 
 |  | 
 |  | 
 | def digest(key, msg, digest): | 
 |     """Fast inline implementation of HMAC. | 
 |  | 
 |     key: bytes or buffer, The key for the keyed hash object. | 
 |     msg: bytes or buffer, Input message. | 
 |     digest: A hash name suitable for hashlib.new() for best performance. *OR* | 
 |             A hashlib constructor returning a new hash object. *OR* | 
 |             A module supporting PEP 247. | 
 |     """ | 
 |     if (_hashopenssl is not None and | 
 |             isinstance(digest, str) and digest in _openssl_md_meths): | 
 |         return _hashopenssl.hmac_digest(key, msg, digest) | 
 |  | 
 |     if callable(digest): | 
 |         digest_cons = digest | 
 |     elif isinstance(digest, str): | 
 |         digest_cons = lambda d=b'': _hashlib.new(digest, d) | 
 |     else: | 
 |         digest_cons = lambda d=b'': digest.new(d) | 
 |  | 
 |     inner = digest_cons() | 
 |     outer = digest_cons() | 
 |     blocksize = getattr(inner, 'block_size', 64) | 
 |     if len(key) > blocksize: | 
 |         key = digest_cons(key).digest() | 
 |     key = key + b'\x00' * (blocksize - len(key)) | 
 |     inner.update(key.translate(trans_36)) | 
 |     outer.update(key.translate(trans_5C)) | 
 |     inner.update(msg) | 
 |     outer.update(inner.digest()) | 
 |     return outer.digest() |