mirror of
https://github.com/python/cpython.git
synced 2025-10-09 08:31:26 +00:00
bpo-32433: Optimized HMAC digest (#5023)
The hmac module now has hmac.digest(), which provides an optimized HMAC digest for short messages. hmac.digest() is up to three times faster than hmac.HMAC().digest(). Signed-off-by: Christian Heimes <christian@python.org>
This commit is contained in:
parent
a49ac99029
commit
2f050c7e1b
7 changed files with 204 additions and 3 deletions
42
Lib/hmac.py
42
Lib/hmac.py
|
@ -5,6 +5,13 @@ 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))
|
||||
|
@ -142,3 +149,38 @@ def new(key, msg = None, digestmod = None):
|
|||
method.
|
||||
"""
|
||||
return HMAC(key, msg, digestmod)
|
||||
|
||||
|
||||
def digest(key, msg, digest):
|
||||
"""Fast inline implementation of HMAC
|
||||
|
||||
key: key for the keyed hash object.
|
||||
msg: 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.
|
||||
|
||||
Note: key and msg must be a bytes or bytearray objects.
|
||||
"""
|
||||
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()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue