Как реализовать HMAC в python без использования библиотеки hmac? - PullRequest
0 голосов
/ 09 мая 2019

Я хочу реализовать алгоритм hmac с SHA-1 по определению из RFC 2104. Код выполняется, но результаты не совпадают с тестовыми векторами из RFC . Я не уверен, правильно ли я загружаю значения (String to Hex или String to Bytes?).

В качестве шаблона я использовал псевдокод из википедии

Я не уверен насчет терминов «размер блока» и «размер вывода». В коде из википедии выходной размер является одним из входных значений, но никогда не используется.

Это мой код: Сначала я настраиваю хеш-функцию, затем я конвертирую мои строки ввода (ключ и сообщение) в шестнадцатеричные значения. Следующим шагом является поиск хэша ключа или его заполнение нулями. Затем я добавляю отдельные символы из ключа с этими значениями (я не знаю, откуда они берутся, но они в каждом примере без каких-либо комментариев). И последнее, но не менее важное: я объединяю внутреннюю строку (I_key_pad + message) и хеширую ее, в результате чего получаются внешние строки, которые я объединяю с внешней панелью и снова хеширую.

    import hashlib
    from functools import reduce


    def hmac(key, message, hashfunc):
        hasher = hashlib.sha1
        blocksize = 40
        message = toHex(message) #is this right?
        key = toHex(key)
        #alternative: loading values as bytes
        #message = bytes(message, 'utf-8')
        #key = bytes(key, 'utf-8')
        if len(key) > blocksize:
            key = hasher(key)
        else:
            #key = key.ljust(blocksize, '0') #filling from right to left
            #key = key.ljust(blocksize, b'\0') #same as above but for bytes
            key = pad(key, blocksize)  #filling from left to right

        val1 = 0x5c 
        val2 = 0x36 

        i = 0
        o_key_pad = ""
        i_key_pad = ""
        while i < blocksize:
            o_key_pad += str(ord(key[i]) ^ val1)
            i_key_pad += str(ord(key[i]) ^ val2)

            i += 1

        tmp_string = str(i_key_pad) + str(message)
        tmp_string = tmp_string.encode()
        inner_hash = hasher(tmp_string).hexdigest()
        fullstring = str(o_key_pad) + inner_hash
        fullstring = fullstring.encode()
        fullstring = hasher(fullstring).hexdigest()
        print(fullstring)


    def pad(key, blocksize):
        key = str(key)
        while len(key) < blocksize:
            key = '0' + key
        key = key
        return key


    def toHex(s):
        lst = []
        for ch in s:
            hv = hex(ord(ch)).replace('0x', '')
            if len(hv) == 1:
                hv = '0' + hv
            lst.append(hv)

        return reduce(lambda x, y: x + y, lst)



    def main():
        while (1):
            key = input("key = ")
            message = input("message = ")
            hash = input("hash (0: SHA-256, 1: SHA-1) = ")
            hmac(key, message, hash)


    if __name__ == "__main__":
        main()

1 Ответ

0 голосов
/ 11 мая 2019

Я не понимаю все шаги в вашем коде, но вот небольшой пример, показывающий, что HMAC-SHA1 использует только hashlib.sha1 с вспомогательной функцией xor.

import hashlib

def xor(x, y):
    return bytes(x[i] ^ y[i] for i in range(min(len(x), len(y))))

def hmac_sha1(key_K, data):
    if len(key_K) > 64:
        raise ValueError('The key must be <= 64 bytes in length')
    padded_K = key_K + b'\x00' * (64 - len(key_K))
    ipad = b'\x36' * 64
    opad = b'\x5c' * 64
    h_inner = hashlib.sha1(xor(padded_K, ipad))
    h_inner.update(data)
    h_outer = hashlib.sha1(xor(padded_K, opad))
    h_outer.update(h_inner.digest())
    return h_outer.digest()


def do_tests():
    # test 1
    k = b'\x0b' * 20
    data = b"Hi There"
    result = hmac_sha1(k, data)
    print(result.hex())
    # add tests as desired
...