◐ Shell
reader mode source ↗
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
File filter
Conversations
Jump to
Diff view
Apply and reload
Show whitespace
Diff view
Apply and reload
6 changes: 6 additions & 0 deletions Doc/library/hmac.rst
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ A hash object has the following attributes:
.. versionadded:: 3.4


This module also provides the following helper function:

.. function:: compare_digest(a, b)
52 changes: 34 additions & 18 deletions Lib/hmac.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ class HMAC:
"""
blocksize = 64 # 512-bit HMAC; can be changed in subclasses.

def __init__(self, key, msg=None, digestmod=''):
"""Create a new HMAC object.

Expand All @@ -51,18 +55,18 @@ def __init__(self, key, msg=None, 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),
Expand All @@ -79,21 +83,33 @@ def __init__(self, key, msg=None, digestmod=''):
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.
Expand All @@ -102,19 +118,19 @@ def copy(self):
"""
# 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):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Toggle all file notes Toggle all file annotations