Я хочу реализовать алгоритм 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()