Search code examples
pythonpython-3.xhashhashmaphmac

How to add another parameter for message in hmac?


i want to write a hmac (hash-based message authentication code) in python. So far i managed to write the basic hmac but i want to add another parameter in the message. For example, message=(mac_address || index_value). Can somebody show me how to do it? And how can i save the output in another list (e.g. digest_hmac_list)?

from hashlib import shake_256
from zlib import crc32, adler32


class HMAC:


    def __init__(self, key, message, hash_h=shake_256):

        """ key and message must be byte object """
        self.i_key_pad = bytearray()
        self.o_key_pad = bytearray()
        self.key = key
        self.message = message
        self.blocksize = 64
        self.hash_h = hash_h
        self.init_flag = False


    def init_pads(self):

        """ creating inner padding and outer padding """
        for i in range(self.blocksize):
            self.i_key_pad.append(0x36 ^ self.key[i])
            self.o_key_pad.append(0x5c ^ self.key[i])


    def init_key(self):

        """ key regeneration """
        if len(self.key) > self.blocksize:
            self.key = bytearray(shake_256(key).digest())
        elif len(self.key) < self.blocksize:
            i = len(self.key)
            while i < self.blocksize:
                self.key += b"\x00"
                i += 1


    def digest(self):

        if self.hash_h == adler32 or self.hash_h == crc32:
            return self.hash_h(bytes(self.o_key_pad)+str(self.hash_h(bytes(self.i_key_pad)+self.message)).encode())
        """ returns a digest, byte object. """
        """ check if init_flag is set """
        if self.init_flag == False:

            self.init_key()
            self.init_pads()

            """ hold init_flag for good. """
            self.init_flag = True

        return self.hash_h(bytes(self.o_key_pad)+self.hash_h(bytes(self.i_key_pad)+self.message).digest()).digest()


    def hexdigest(self):

        if self.hash_h == adler32 or self.hash_h == crc32:
            return hex(self.hash_h(bytes(self.o_key_pad)+str(self.hash_h(bytes(self.i_key_pad)+self.message)).encode()))[2:]

        """ returns a digest in hexadecimal. """
        """ check if init_flag is set """
        if self.init_flag == False:

            """ init key and padding. """
            self.init_key()
            self.init_pads()

            """ set init_flag for good. """
            self.init_flag = True

Solution

  • I fixed some small issues in Your code and made it so you can hash 2 different (mac || index) with same key and save it in a self.digest_all_list. I commented out all these things in the code.

    from hashlib import shake_256
    from zlib import crc32, adler32
    
    
    class HMAC:
        def __init__(self, key, message, hash_h=shake_256):
    
            """ key and message must be byte object """
            self.i_key_pad = bytearray()
            self.o_key_pad = bytearray()
            self.key = key
            self.message = message
            self.blocksize = 64
            self.hash_h = hash_h
            self.init_flag = False
    
            # This will contain all hashed messages
            self.digest_hmac_list = []
    
        def init_pads(self):
    
            """ creating inner padding and outer padding """
            for i in range(self.blocksize):
                self.i_key_pad.append(0x36 ^ self.key[i])
                self.o_key_pad.append(0x5c ^ self.key[i])
    
    
        def init_key(self):
    
            """ key regeneration """
            if len(self.key) > self.blocksize:
                self.key = bytearray(shake_256(self.key).digest(self.blocksize))
            elif len(self.key) < self.blocksize:
                i = len(self.key)
                while i < self.blocksize:
                    self.key += b"\x00"
                    i += 1
    
    
        def digest(self, message = None):
    
            # If you want to Hash 2 different message with same key(so same class instance)
            # pass message to digest and default to self.message
            if message:
                self.message = bytearray(message, encoding="ascii")
    
            if self.hash_h == adler32 or self.hash_h == crc32:
                return self.hash_h(bytes(self.o_key_pad)+str(self.hash_h(bytes(self.i_key_pad)+self.message)).encode())
            """ returns a digest, byte object. """
            """ check if init_flag is set """
            if self.init_flag == False:
    
                self.init_key()
                self.init_pads()
    
                """ hold init_flag for good. """
                self.init_flag = True
    
            # You Forget to specify the size of the Hash shake_256 allow for arbitrary output(Not like SHA-2)
            # , I chosen 64 byte you can you chose whatever you want
            self.digest_hmac_list.append(self.hash_h(bytes(self.o_key_pad) + self.hash_h(bytes(self.i_key_pad) + self.message).digest(self.blocksize)).digest(self.blocksize))
            return self.digest_hmac_list[-1]
    
    
        def hexdigest(self, message = None):
    
            # If you want to Hash 2 different message with same key(so same class instance)
            # pass message to digest and default to self.message
            if message:
                self.message = bytearray(message, encoding="ascii")
    
                # Checking must be Done First So you can initialize all required parts then hash the message
            """ check if init_flag is set """
            if self.init_flag == False:
    
                """ init key and padding. """
                self.init_key()
                self.init_pads()
    
                """ set init_flag for good. """
                self.init_flag = True
    
            if self.hash_h == adler32 or self.hash_h == crc32:
                self.digest_hmac_list.append(hex(self.hash_h(bytes(self.o_key_pad) + str(self.hash_h(bytes(self.i_key_pad) + self.message)).encode())[2:]))
                return self.digest_hmac_list[-1]
            """ returns a digest in hexadecimal. """
    
            # NOTE: You are Not hashing anything if the default Hash function is shake_256, add
            # code here to add hexHashing for default
    
    # message is mac then post pended with Index if that what I understand
    index = "0"
    mac = "FF0A8CD1DAAB"
    key = "This is key"
    cl = HMAC(bytearray(key, encoding="ascii"), bytearray(mac + index, encoding="ascii"), shake_256)
    print(cl.digest())
    print("=="*10)
    
    index = "1"
    print(cl.digest(mac + index))
    print("=="*10)
    print(cl.digest_hmac_list)