17db96d56Sopenharmony_ci"""HMAC (Keyed-Hashing for Message Authentication) module. 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ciImplements the HMAC algorithm as described by RFC 2104. 47db96d56Sopenharmony_ci""" 57db96d56Sopenharmony_ci 67db96d56Sopenharmony_ciimport warnings as _warnings 77db96d56Sopenharmony_citry: 87db96d56Sopenharmony_ci import _hashlib as _hashopenssl 97db96d56Sopenharmony_ciexcept ImportError: 107db96d56Sopenharmony_ci _hashopenssl = None 117db96d56Sopenharmony_ci _functype = None 127db96d56Sopenharmony_ci from _operator import _compare_digest as compare_digest 137db96d56Sopenharmony_cielse: 147db96d56Sopenharmony_ci compare_digest = _hashopenssl.compare_digest 157db96d56Sopenharmony_ci _functype = type(_hashopenssl.openssl_sha256) # builtin type 167db96d56Sopenharmony_ci 177db96d56Sopenharmony_ciimport hashlib as _hashlib 187db96d56Sopenharmony_ci 197db96d56Sopenharmony_citrans_5C = bytes((x ^ 0x5C) for x in range(256)) 207db96d56Sopenharmony_citrans_36 = bytes((x ^ 0x36) for x in range(256)) 217db96d56Sopenharmony_ci 227db96d56Sopenharmony_ci# The size of the digests returned by HMAC depends on the underlying 237db96d56Sopenharmony_ci# hashing module used. Use digest_size from the instance of HMAC instead. 247db96d56Sopenharmony_cidigest_size = None 257db96d56Sopenharmony_ci 267db96d56Sopenharmony_ci 277db96d56Sopenharmony_ciclass HMAC: 287db96d56Sopenharmony_ci """RFC 2104 HMAC class. Also complies with RFC 4231. 297db96d56Sopenharmony_ci 307db96d56Sopenharmony_ci This supports the API for Cryptographic Hash Functions (PEP 247). 317db96d56Sopenharmony_ci """ 327db96d56Sopenharmony_ci blocksize = 64 # 512-bit HMAC; can be changed in subclasses. 337db96d56Sopenharmony_ci 347db96d56Sopenharmony_ci __slots__ = ( 357db96d56Sopenharmony_ci "_hmac", "_inner", "_outer", "block_size", "digest_size" 367db96d56Sopenharmony_ci ) 377db96d56Sopenharmony_ci 387db96d56Sopenharmony_ci def __init__(self, key, msg=None, digestmod=''): 397db96d56Sopenharmony_ci """Create a new HMAC object. 407db96d56Sopenharmony_ci 417db96d56Sopenharmony_ci key: bytes or buffer, key for the keyed hash object. 427db96d56Sopenharmony_ci msg: bytes or buffer, Initial input for the hash or None. 437db96d56Sopenharmony_ci digestmod: A hash name suitable for hashlib.new(). *OR* 447db96d56Sopenharmony_ci A hashlib constructor returning a new hash object. *OR* 457db96d56Sopenharmony_ci A module supporting PEP 247. 467db96d56Sopenharmony_ci 477db96d56Sopenharmony_ci Required as of 3.8, despite its position after the optional 487db96d56Sopenharmony_ci msg argument. Passing it as a keyword argument is 497db96d56Sopenharmony_ci recommended, though not required for legacy API reasons. 507db96d56Sopenharmony_ci """ 517db96d56Sopenharmony_ci 527db96d56Sopenharmony_ci if not isinstance(key, (bytes, bytearray)): 537db96d56Sopenharmony_ci raise TypeError("key: expected bytes or bytearray, but got %r" % type(key).__name__) 547db96d56Sopenharmony_ci 557db96d56Sopenharmony_ci if not digestmod: 567db96d56Sopenharmony_ci raise TypeError("Missing required parameter 'digestmod'.") 577db96d56Sopenharmony_ci 587db96d56Sopenharmony_ci if _hashopenssl and isinstance(digestmod, (str, _functype)): 597db96d56Sopenharmony_ci try: 607db96d56Sopenharmony_ci self._init_hmac(key, msg, digestmod) 617db96d56Sopenharmony_ci except _hashopenssl.UnsupportedDigestmodError: 627db96d56Sopenharmony_ci self._init_old(key, msg, digestmod) 637db96d56Sopenharmony_ci else: 647db96d56Sopenharmony_ci self._init_old(key, msg, digestmod) 657db96d56Sopenharmony_ci 667db96d56Sopenharmony_ci def _init_hmac(self, key, msg, digestmod): 677db96d56Sopenharmony_ci self._hmac = _hashopenssl.hmac_new(key, msg, digestmod=digestmod) 687db96d56Sopenharmony_ci self.digest_size = self._hmac.digest_size 697db96d56Sopenharmony_ci self.block_size = self._hmac.block_size 707db96d56Sopenharmony_ci 717db96d56Sopenharmony_ci def _init_old(self, key, msg, digestmod): 727db96d56Sopenharmony_ci if callable(digestmod): 737db96d56Sopenharmony_ci digest_cons = digestmod 747db96d56Sopenharmony_ci elif isinstance(digestmod, str): 757db96d56Sopenharmony_ci digest_cons = lambda d=b'': _hashlib.new(digestmod, d) 767db96d56Sopenharmony_ci else: 777db96d56Sopenharmony_ci digest_cons = lambda d=b'': digestmod.new(d) 787db96d56Sopenharmony_ci 797db96d56Sopenharmony_ci self._hmac = None 807db96d56Sopenharmony_ci self._outer = digest_cons() 817db96d56Sopenharmony_ci self._inner = digest_cons() 827db96d56Sopenharmony_ci self.digest_size = self._inner.digest_size 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ci if hasattr(self._inner, 'block_size'): 857db96d56Sopenharmony_ci blocksize = self._inner.block_size 867db96d56Sopenharmony_ci if blocksize < 16: 877db96d56Sopenharmony_ci _warnings.warn('block_size of %d seems too small; using our ' 887db96d56Sopenharmony_ci 'default of %d.' % (blocksize, self.blocksize), 897db96d56Sopenharmony_ci RuntimeWarning, 2) 907db96d56Sopenharmony_ci blocksize = self.blocksize 917db96d56Sopenharmony_ci else: 927db96d56Sopenharmony_ci _warnings.warn('No block_size attribute on given digest object; ' 937db96d56Sopenharmony_ci 'Assuming %d.' % (self.blocksize), 947db96d56Sopenharmony_ci RuntimeWarning, 2) 957db96d56Sopenharmony_ci blocksize = self.blocksize 967db96d56Sopenharmony_ci 977db96d56Sopenharmony_ci if len(key) > blocksize: 987db96d56Sopenharmony_ci key = digest_cons(key).digest() 997db96d56Sopenharmony_ci 1007db96d56Sopenharmony_ci # self.blocksize is the default blocksize. self.block_size is 1017db96d56Sopenharmony_ci # effective block size as well as the public API attribute. 1027db96d56Sopenharmony_ci self.block_size = blocksize 1037db96d56Sopenharmony_ci 1047db96d56Sopenharmony_ci key = key.ljust(blocksize, b'\0') 1057db96d56Sopenharmony_ci self._outer.update(key.translate(trans_5C)) 1067db96d56Sopenharmony_ci self._inner.update(key.translate(trans_36)) 1077db96d56Sopenharmony_ci if msg is not None: 1087db96d56Sopenharmony_ci self.update(msg) 1097db96d56Sopenharmony_ci 1107db96d56Sopenharmony_ci @property 1117db96d56Sopenharmony_ci def name(self): 1127db96d56Sopenharmony_ci if self._hmac: 1137db96d56Sopenharmony_ci return self._hmac.name 1147db96d56Sopenharmony_ci else: 1157db96d56Sopenharmony_ci return f"hmac-{self._inner.name}" 1167db96d56Sopenharmony_ci 1177db96d56Sopenharmony_ci def update(self, msg): 1187db96d56Sopenharmony_ci """Feed data from msg into this hashing object.""" 1197db96d56Sopenharmony_ci inst = self._hmac or self._inner 1207db96d56Sopenharmony_ci inst.update(msg) 1217db96d56Sopenharmony_ci 1227db96d56Sopenharmony_ci def copy(self): 1237db96d56Sopenharmony_ci """Return a separate copy of this hashing object. 1247db96d56Sopenharmony_ci 1257db96d56Sopenharmony_ci An update to this copy won't affect the original object. 1267db96d56Sopenharmony_ci """ 1277db96d56Sopenharmony_ci # Call __new__ directly to avoid the expensive __init__. 1287db96d56Sopenharmony_ci other = self.__class__.__new__(self.__class__) 1297db96d56Sopenharmony_ci other.digest_size = self.digest_size 1307db96d56Sopenharmony_ci if self._hmac: 1317db96d56Sopenharmony_ci other._hmac = self._hmac.copy() 1327db96d56Sopenharmony_ci other._inner = other._outer = None 1337db96d56Sopenharmony_ci else: 1347db96d56Sopenharmony_ci other._hmac = None 1357db96d56Sopenharmony_ci other._inner = self._inner.copy() 1367db96d56Sopenharmony_ci other._outer = self._outer.copy() 1377db96d56Sopenharmony_ci return other 1387db96d56Sopenharmony_ci 1397db96d56Sopenharmony_ci def _current(self): 1407db96d56Sopenharmony_ci """Return a hash object for the current state. 1417db96d56Sopenharmony_ci 1427db96d56Sopenharmony_ci To be used only internally with digest() and hexdigest(). 1437db96d56Sopenharmony_ci """ 1447db96d56Sopenharmony_ci if self._hmac: 1457db96d56Sopenharmony_ci return self._hmac 1467db96d56Sopenharmony_ci else: 1477db96d56Sopenharmony_ci h = self._outer.copy() 1487db96d56Sopenharmony_ci h.update(self._inner.digest()) 1497db96d56Sopenharmony_ci return h 1507db96d56Sopenharmony_ci 1517db96d56Sopenharmony_ci def digest(self): 1527db96d56Sopenharmony_ci """Return the hash value of this hashing object. 1537db96d56Sopenharmony_ci 1547db96d56Sopenharmony_ci This returns the hmac value as bytes. The object is 1557db96d56Sopenharmony_ci not altered in any way by this function; you can continue 1567db96d56Sopenharmony_ci updating the object after calling this function. 1577db96d56Sopenharmony_ci """ 1587db96d56Sopenharmony_ci h = self._current() 1597db96d56Sopenharmony_ci return h.digest() 1607db96d56Sopenharmony_ci 1617db96d56Sopenharmony_ci def hexdigest(self): 1627db96d56Sopenharmony_ci """Like digest(), but returns a string of hexadecimal digits instead. 1637db96d56Sopenharmony_ci """ 1647db96d56Sopenharmony_ci h = self._current() 1657db96d56Sopenharmony_ci return h.hexdigest() 1667db96d56Sopenharmony_ci 1677db96d56Sopenharmony_cidef new(key, msg=None, digestmod=''): 1687db96d56Sopenharmony_ci """Create a new hashing object and return it. 1697db96d56Sopenharmony_ci 1707db96d56Sopenharmony_ci key: bytes or buffer, The starting key for the hash. 1717db96d56Sopenharmony_ci msg: bytes or buffer, Initial input for the hash, or None. 1727db96d56Sopenharmony_ci digestmod: A hash name suitable for hashlib.new(). *OR* 1737db96d56Sopenharmony_ci A hashlib constructor returning a new hash object. *OR* 1747db96d56Sopenharmony_ci A module supporting PEP 247. 1757db96d56Sopenharmony_ci 1767db96d56Sopenharmony_ci Required as of 3.8, despite its position after the optional 1777db96d56Sopenharmony_ci msg argument. Passing it as a keyword argument is 1787db96d56Sopenharmony_ci recommended, though not required for legacy API reasons. 1797db96d56Sopenharmony_ci 1807db96d56Sopenharmony_ci You can now feed arbitrary bytes into the object using its update() 1817db96d56Sopenharmony_ci method, and can ask for the hash value at any time by calling its digest() 1827db96d56Sopenharmony_ci or hexdigest() methods. 1837db96d56Sopenharmony_ci """ 1847db96d56Sopenharmony_ci return HMAC(key, msg, digestmod) 1857db96d56Sopenharmony_ci 1867db96d56Sopenharmony_ci 1877db96d56Sopenharmony_cidef digest(key, msg, digest): 1887db96d56Sopenharmony_ci """Fast inline implementation of HMAC. 1897db96d56Sopenharmony_ci 1907db96d56Sopenharmony_ci key: bytes or buffer, The key for the keyed hash object. 1917db96d56Sopenharmony_ci msg: bytes or buffer, Input message. 1927db96d56Sopenharmony_ci digest: A hash name suitable for hashlib.new() for best performance. *OR* 1937db96d56Sopenharmony_ci A hashlib constructor returning a new hash object. *OR* 1947db96d56Sopenharmony_ci A module supporting PEP 247. 1957db96d56Sopenharmony_ci """ 1967db96d56Sopenharmony_ci if _hashopenssl is not None and isinstance(digest, (str, _functype)): 1977db96d56Sopenharmony_ci try: 1987db96d56Sopenharmony_ci return _hashopenssl.hmac_digest(key, msg, digest) 1997db96d56Sopenharmony_ci except _hashopenssl.UnsupportedDigestmodError: 2007db96d56Sopenharmony_ci pass 2017db96d56Sopenharmony_ci 2027db96d56Sopenharmony_ci if callable(digest): 2037db96d56Sopenharmony_ci digest_cons = digest 2047db96d56Sopenharmony_ci elif isinstance(digest, str): 2057db96d56Sopenharmony_ci digest_cons = lambda d=b'': _hashlib.new(digest, d) 2067db96d56Sopenharmony_ci else: 2077db96d56Sopenharmony_ci digest_cons = lambda d=b'': digest.new(d) 2087db96d56Sopenharmony_ci 2097db96d56Sopenharmony_ci inner = digest_cons() 2107db96d56Sopenharmony_ci outer = digest_cons() 2117db96d56Sopenharmony_ci blocksize = getattr(inner, 'block_size', 64) 2127db96d56Sopenharmony_ci if len(key) > blocksize: 2137db96d56Sopenharmony_ci key = digest_cons(key).digest() 2147db96d56Sopenharmony_ci key = key + b'\x00' * (blocksize - len(key)) 2157db96d56Sopenharmony_ci inner.update(key.translate(trans_36)) 2167db96d56Sopenharmony_ci outer.update(key.translate(trans_5C)) 2177db96d56Sopenharmony_ci inner.update(msg) 2187db96d56Sopenharmony_ci outer.update(inner.digest()) 2197db96d56Sopenharmony_ci return outer.digest() 220