python-2.5.2/win32/Lib/hmac.py
changeset 0 ae805ac0140d
equal deleted inserted replaced
-1:000000000000 0:ae805ac0140d
       
     1 """HMAC (Keyed-Hashing for Message Authentication) Python module.
       
     2 
       
     3 Implements the HMAC algorithm as described by RFC 2104.
       
     4 """
       
     5 
       
     6 def _strxor(s1, s2):
       
     7     """Utility method. XOR the two strings s1 and s2 (must have same length).
       
     8     """
       
     9     return "".join(map(lambda x, y: chr(ord(x) ^ ord(y)), s1, s2))
       
    10 
       
    11 # The size of the digests returned by HMAC depends on the underlying
       
    12 # hashing module used.
       
    13 digest_size = None
       
    14 
       
    15 # A unique object passed by HMAC.copy() to the HMAC constructor, in order
       
    16 # that the latter return very quickly.  HMAC("") in contrast is quite
       
    17 # expensive.
       
    18 _secret_backdoor_key = []
       
    19 
       
    20 class HMAC:
       
    21     """RFC2104 HMAC class.
       
    22 
       
    23     This supports the API for Cryptographic Hash Functions (PEP 247).
       
    24     """
       
    25 
       
    26     def __init__(self, key, msg = None, digestmod = None):
       
    27         """Create a new HMAC object.
       
    28 
       
    29         key:       key for the keyed hash object.
       
    30         msg:       Initial input for the hash, if provided.
       
    31         digestmod: A module supporting PEP 247.  *OR*
       
    32                    A hashlib constructor returning a new hash object.
       
    33                    Defaults to hashlib.md5.
       
    34         """
       
    35 
       
    36         if key is _secret_backdoor_key: # cheap
       
    37             return
       
    38 
       
    39         if digestmod is None:
       
    40             import hashlib
       
    41             digestmod = hashlib.md5
       
    42 
       
    43         if callable(digestmod):
       
    44             self.digest_cons = digestmod
       
    45         else:
       
    46             self.digest_cons = lambda d='': digestmod.new(d)
       
    47 
       
    48         self.outer = self.digest_cons()
       
    49         self.inner = self.digest_cons()
       
    50         self.digest_size = self.inner.digest_size
       
    51 
       
    52         if hasattr(self.inner, 'block_size'):
       
    53             blocksize = self.inner.block_size
       
    54             if blocksize < 16:
       
    55                 # Very low blocksize, most likely a legacy value like
       
    56                 # Lib/sha.py and Lib/md5.py have.
       
    57                 blocksize = 64
       
    58         else:
       
    59             blocksize = 64
       
    60 
       
    61         ipad = "\x36" * blocksize
       
    62         opad = "\x5C" * blocksize
       
    63 
       
    64         if len(key) > blocksize:
       
    65             key = self.digest_cons(key).digest()
       
    66 
       
    67         key = key + chr(0) * (blocksize - len(key))
       
    68         self.outer.update(_strxor(key, opad))
       
    69         self.inner.update(_strxor(key, ipad))
       
    70         if msg is not None:
       
    71             self.update(msg)
       
    72 
       
    73 ##    def clear(self):
       
    74 ##        raise NotImplementedError, "clear() method not available in HMAC."
       
    75 
       
    76     def update(self, msg):
       
    77         """Update this hashing object with the string msg.
       
    78         """
       
    79         self.inner.update(msg)
       
    80 
       
    81     def copy(self):
       
    82         """Return a separate copy of this hashing object.
       
    83 
       
    84         An update to this copy won't affect the original object.
       
    85         """
       
    86         other = HMAC(_secret_backdoor_key)
       
    87         other.digest_cons = self.digest_cons
       
    88         other.digest_size = self.digest_size
       
    89         other.inner = self.inner.copy()
       
    90         other.outer = self.outer.copy()
       
    91         return other
       
    92 
       
    93     def digest(self):
       
    94         """Return the hash value of this hashing object.
       
    95 
       
    96         This returns a string containing 8-bit data.  The object is
       
    97         not altered in any way by this function; you can continue
       
    98         updating the object after calling this function.
       
    99         """
       
   100         h = self.outer.copy()
       
   101         h.update(self.inner.digest())
       
   102         return h.digest()
       
   103 
       
   104     def hexdigest(self):
       
   105         """Like digest(), but returns a string of hexadecimal digits instead.
       
   106         """
       
   107         return "".join([hex(ord(x))[2:].zfill(2)
       
   108                         for x in tuple(self.digest())])
       
   109 
       
   110 def new(key, msg = None, digestmod = None):
       
   111     """Create a new hashing object and return it.
       
   112 
       
   113     key: The starting key for the hash.
       
   114     msg: if available, will immediately be hashed into the object's starting
       
   115     state.
       
   116 
       
   117     You can now feed arbitrary strings into the object using its update()
       
   118     method, and can ask for the hash value at any time by calling its digest()
       
   119     method.
       
   120     """
       
   121     return HMAC(key, msg, digestmod)