Blame Lib/hmac.py

rpm-build 2bd099
"""HMAC (Keyed-Hashing for Message Authentication) Python module.
rpm-build 2bd099
rpm-build 2bd099
Implements the HMAC algorithm as described by RFC 2104.
rpm-build 2bd099
"""
rpm-build 2bd099
rpm-build 2bd099
import warnings as _warnings
rpm-build 2bd099
from _operator import _compare_digest as compare_digest
rpm-build 2bd099
import hashlib as _hashlib
rpm-build 2bd099
rpm-build 2bd099
trans_5C = bytes((x ^ 0x5C) for x in range(256))
rpm-build 2bd099
trans_36 = bytes((x ^ 0x36) for x in range(256))
rpm-build 2bd099
rpm-build 2bd099
# The size of the digests returned by HMAC depends on the underlying
rpm-build 2bd099
# hashing module used.  Use digest_size from the instance of HMAC instead.
rpm-build 2bd099
digest_size = None
rpm-build 2bd099
rpm-build 2bd099
rpm-build 2bd099
rpm-build 2bd099
class HMAC:
rpm-build 2bd099
    """RFC 2104 HMAC class.  Also complies with RFC 4231.
rpm-build 2bd099
rpm-build 2bd099
    This supports the API for Cryptographic Hash Functions (PEP 247).
rpm-build 2bd099
    """
rpm-build 2bd099
    blocksize = 64  # 512-bit HMAC; can be changed in subclasses.
rpm-build 2bd099
rpm-build 2bd099
    def __init__(self, key, msg = None, digestmod = None):
rpm-build 2bd099
        """Create a new HMAC object.
rpm-build 2bd099
rpm-build 2bd099
        key:       key for the keyed hash object.
rpm-build 2bd099
        msg:       Initial input for the hash, if provided.
rpm-build 2bd099
        digestmod: A module supporting PEP 247.  *OR*
rpm-build 2bd099
                   A hashlib constructor returning a new hash object. *OR*
rpm-build 2bd099
                   A hash name suitable for hashlib.new().
rpm-build 2bd099
                   Defaults to hashlib.md5.
rpm-build 2bd099
                   Implicit default to hashlib.md5 is deprecated and will be
rpm-build 2bd099
                   removed in Python 3.6.
rpm-build 2bd099
rpm-build 2bd099
        Note: key and msg must be a bytes or bytearray objects.
rpm-build 2bd099
        """
rpm-build 2bd099
rpm-build 2bd099
        if not isinstance(key, (bytes, bytearray)):
rpm-build 2bd099
            raise TypeError("key: expected bytes or bytearray, but got %r" % type(key).__name__)
rpm-build 2bd099
rpm-build 2bd099
        if digestmod is None:
rpm-build 2bd099
            _warnings.warn("HMAC() without an explicit digestmod argument "
rpm-build 2bd099
                           "is deprecated.", PendingDeprecationWarning, 2)
rpm-build 2bd099
            digestmod = _hashlib.md5
rpm-build 2bd099
rpm-build 2bd099
        if callable(digestmod):
rpm-build 2bd099
            self.digest_cons = digestmod
rpm-build 2bd099
        elif isinstance(digestmod, str):
rpm-build 2bd099
            self.digest_cons = lambda d=b'': _hashlib.new(digestmod, d)
rpm-build 2bd099
        else:
rpm-build 2bd099
            self.digest_cons = lambda d=b'': digestmod.new(d)
rpm-build 2bd099
rpm-build 2bd099
        self.outer = self.digest_cons()
rpm-build 2bd099
        self.inner = self.digest_cons()
rpm-build 2bd099
        self.digest_size = self.inner.digest_size
rpm-build 2bd099
rpm-build 2bd099
        if hasattr(self.inner, 'block_size'):
rpm-build 2bd099
            blocksize = self.inner.block_size
rpm-build 2bd099
            if blocksize < 16:
rpm-build 2bd099
                _warnings.warn('block_size of %d seems too small; using our '
rpm-build 2bd099
                               'default of %d.' % (blocksize, self.blocksize),
rpm-build 2bd099
                               RuntimeWarning, 2)
rpm-build 2bd099
                blocksize = self.blocksize
rpm-build 2bd099
        else:
rpm-build 2bd099
            _warnings.warn('No block_size attribute on given digest object; '
rpm-build 2bd099
                           'Assuming %d.' % (self.blocksize),
rpm-build 2bd099
                           RuntimeWarning, 2)
rpm-build 2bd099
            blocksize = self.blocksize
rpm-build 2bd099
rpm-build 2bd099
        # self.blocksize is the default blocksize. self.block_size is
rpm-build 2bd099
        # effective block size as well as the public API attribute.
rpm-build 2bd099
        self.block_size = blocksize
rpm-build 2bd099
rpm-build 2bd099
        if len(key) > blocksize:
rpm-build 2bd099
            key = self.digest_cons(key).digest()
rpm-build 2bd099
rpm-build 2bd099
        key = key.ljust(blocksize, b'\0')
rpm-build 2bd099
        self.outer.update(key.translate(trans_5C))
rpm-build 2bd099
        self.inner.update(key.translate(trans_36))
rpm-build 2bd099
        if msg is not None:
rpm-build 2bd099
            self.update(msg)
rpm-build 2bd099
rpm-build 2bd099
    @property
rpm-build 2bd099
    def name(self):
rpm-build 2bd099
        return "hmac-" + self.inner.name
rpm-build 2bd099
rpm-build 2bd099
    def update(self, msg):
rpm-build 2bd099
        """Update this hashing object with the string msg.
rpm-build 2bd099
        """
rpm-build 2bd099
        self.inner.update(msg)
rpm-build 2bd099
rpm-build 2bd099
    def copy(self):
rpm-build 2bd099
        """Return a separate copy of this hashing object.
rpm-build 2bd099
rpm-build 2bd099
        An update to this copy won't affect the original object.
rpm-build 2bd099
        """
rpm-build 2bd099
        # Call __new__ directly to avoid the expensive __init__.
rpm-build 2bd099
        other = self.__class__.__new__(self.__class__)
rpm-build 2bd099
        other.digest_cons = self.digest_cons
rpm-build 2bd099
        other.digest_size = self.digest_size
rpm-build 2bd099
        other.inner = self.inner.copy()
rpm-build 2bd099
        other.outer = self.outer.copy()
rpm-build 2bd099
        return other
rpm-build 2bd099
rpm-build 2bd099
    def _current(self):
rpm-build 2bd099
        """Return a hash object for the current state.
rpm-build 2bd099
rpm-build 2bd099
        To be used only internally with digest() and hexdigest().
rpm-build 2bd099
        """
rpm-build 2bd099
        h = self.outer.copy()
rpm-build 2bd099
        h.update(self.inner.digest())
rpm-build 2bd099
        return h
rpm-build 2bd099
rpm-build 2bd099
    def digest(self):
rpm-build 2bd099
        """Return the hash value of this hashing object.
rpm-build 2bd099
rpm-build 2bd099
        This returns a string containing 8-bit data.  The object is
rpm-build 2bd099
        not altered in any way by this function; you can continue
rpm-build 2bd099
        updating the object after calling this function.
rpm-build 2bd099
        """
rpm-build 2bd099
        h = self._current()
rpm-build 2bd099
        return h.digest()
rpm-build 2bd099
rpm-build 2bd099
    def hexdigest(self):
rpm-build 2bd099
        """Like digest(), but returns a string of hexadecimal digits instead.
rpm-build 2bd099
        """
rpm-build 2bd099
        h = self._current()
rpm-build 2bd099
        return h.hexdigest()
rpm-build 2bd099
rpm-build 2bd099
def new(key, msg = None, digestmod = None):
rpm-build 2bd099
    """Create a new hashing object and return it.
rpm-build 2bd099
rpm-build 2bd099
    key: The starting key for the hash.
rpm-build 2bd099
    msg: if available, will immediately be hashed into the object's starting
rpm-build 2bd099
    state.
rpm-build 2bd099
rpm-build 2bd099
    You can now feed arbitrary strings into the object using its update()
rpm-build 2bd099
    method, and can ask for the hash value at any time by calling its digest()
rpm-build 2bd099
    method.
rpm-build 2bd099
    """
rpm-build 2bd099
    return HMAC(key, msg, digestmod)