15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""HMAC (Keyed-Hashing for Message Authentication) Python module.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Implements the HMAC algorithm as described by RFC 2104.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(This file is modified from the standard library version to do faster
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)copying)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def _strxor(s1, s2):
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Utility method. XOR the two strings s1 and s2 (must have same length).
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "".join(map(lambda x, y: chr(ord(x) ^ ord(y)), s1, s2))
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# The size of the digests returned by HMAC depends on the underlying
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# hashing module used.
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)digest_size = None
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class HMAC:
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """RFC2104 HMAC class.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    This supports the API for Cryptographic Hash Functions (PEP 247).
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __init__(self, key, msg = None, digestmod = None):
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Create a new HMAC object.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        key:       key for the keyed hash object.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        msg:       Initial input for the hash, if provided.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        digestmod: A module supporting PEP 247. Defaults to the md5 module.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if digestmod is None:
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            import md5
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            digestmod = md5
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if key == None: #TREVNEW - for faster copying
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return      #TREVNEW
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.digestmod = digestmod
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.outer = digestmod.new()
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.inner = digestmod.new()
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.digest_size = digestmod.digest_size
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocksize = 64
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ipad = "\x36" * blocksize
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        opad = "\x5C" * blocksize
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if len(key) > blocksize:
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            key = digestmod.new(key).digest()
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        key = key + chr(0) * (blocksize - len(key))
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.outer.update(_strxor(key, opad))
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.inner.update(_strxor(key, ipad))
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if msg is not None:
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.update(msg)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)##    def clear(self):
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)##        raise NotImplementedError, "clear() method not available in HMAC."
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def update(self, msg):
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Update this hashing object with the string msg.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.inner.update(msg)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def copy(self):
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Return a separate copy of this hashing object.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        An update to this copy won't affect the original object.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        other = HMAC(None) #TREVNEW - for faster copying
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        other.digest_size = self.digest_size #TREVNEW
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        other.digestmod = self.digestmod
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        other.inner = self.inner.copy()
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        other.outer = self.outer.copy()
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return other
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def digest(self):
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Return the hash value of this hashing object.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        This returns a string containing 8-bit data.  The object is
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        not altered in any way by this function; you can continue
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        updating the object after calling this function.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        h = self.outer.copy()
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        h.update(self.inner.digest())
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return h.digest()
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def hexdigest(self):
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """Like digest(), but returns a string of hexadecimal digits instead.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        """
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return "".join([hex(ord(x))[2:].zfill(2)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        for x in tuple(self.digest())])
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def new(key, msg = None, digestmod = None):
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Create a new hashing object and return it.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    key: The starting key for the hash.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    msg: if available, will immediately be hashed into the object's starting
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    state.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    You can now feed arbitrary strings into the object using its update()
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    method, and can ask for the hash value at any time by calling its digest()
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    method.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return HMAC(key, msg, digestmod)
105