使用 python 计算字符串的 HMAC 时出现问题
Problem with calculating HMAC of a string with python
我正在尝试编写一个程序来计算字符串的 hmac。我可以使用 hashlib 库,但不能使用 hmac。这是我的代码:
from hashlib import sha256
def string_to_decimal(string):
res = ''
for char in string:
res += hex(ord(char))[2:]
return int(res, 16)
def decimal_to_string(number):
hex_number = hex(number)[2:]
hex_number = hex_number[::-1]
res = ''
for i in range(0, len(hex_number), 2):
if i + 1 < len(hex_number):
res += chr(int(hex_number[i + 1] + hex_number[i], 16))
else:
res += chr(int(hex_number[i], 16))
return res[::-1]
def calculate_ipad_opad(block_size, ipad, opad):
res_ipad = 0
res_opad = 0
for i in range(block_size // 8):
res_ipad = (res_ipad * 256) + ipad
res_opad = (res_opad * 256) + opad
return res_ipad, res_opad
def integer_to_bytes(number):
res = list()
while number > 0:
res.append(number % 256)
number //= 256
return bytes(res[::-1])
block_size = 512
msg = 'The quick brown fox jumps over the lazy dog'
key = 'key'
ipad = 54
opad = 92
block_ipad, block_opad = calculate_ipad_opad(block_size, ipad, opad)
key_decimal = string_to_decimal(key)
si = key_decimal ^ block_ipad
so = key_decimal ^ block_opad
a = sha256(integer_to_bytes(so) + sha256(integer_to_bytes(si) + msg.encode()).digest())
print(a.digest())
我知道密钥长度不超过块大小。我使用 Wikipedia 编写代码。但它不能正常工作。你能帮我解决一下吗???
编辑:
我预计代码的输出为 f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8
。但是输出是 3d6243123b984bcc17cb96eb61c2b47d27545c3a9119b623be7932e846bf0643
.
键的右侧必须用 0x00 值填充到摘要的块大小(如果键大小小于块大小,这里就是这种情况)。您可以通过例如在 return
:
之前添加 string_to_decimal()
res = res.ljust(64 * 2, "0")
通过此更改,提供了预期的结果。
对于实现,最好使用更详细的算法规范,例如FIPS PUB 198-1 instead of the highly abbreviated description in Wikipedia. Furthermore, you are on the safe side if official test vectors 已应用。
实际上不需要转换为十进制数,即可以像对象一样直接使用字节,这大大简化了实现:
from hashlib import sha256
msg = 'The quick brown fox jumps over the lazy dog'
key = 'key'
block_size_bytes = 64
block_opad_bytes = b'\x5c' * block_size_bytes
block_ipad_bytes = b'\x36' * block_size_bytes
key_bytes = key.encode().ljust(block_size_bytes, b'[=11=]')
si_bytes = bytes([a ^ b for (a, b) in zip(block_ipad_bytes, key_bytes)])
so_bytes = bytes([a ^ b for (a, b) in zip(block_opad_bytes, key_bytes)])
a = sha256(so_bytes + sha256(si_bytes + msg.encode()).digest())
print(a.digest().hex()) # f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8
我正在尝试编写一个程序来计算字符串的 hmac。我可以使用 hashlib 库,但不能使用 hmac。这是我的代码:
from hashlib import sha256
def string_to_decimal(string):
res = ''
for char in string:
res += hex(ord(char))[2:]
return int(res, 16)
def decimal_to_string(number):
hex_number = hex(number)[2:]
hex_number = hex_number[::-1]
res = ''
for i in range(0, len(hex_number), 2):
if i + 1 < len(hex_number):
res += chr(int(hex_number[i + 1] + hex_number[i], 16))
else:
res += chr(int(hex_number[i], 16))
return res[::-1]
def calculate_ipad_opad(block_size, ipad, opad):
res_ipad = 0
res_opad = 0
for i in range(block_size // 8):
res_ipad = (res_ipad * 256) + ipad
res_opad = (res_opad * 256) + opad
return res_ipad, res_opad
def integer_to_bytes(number):
res = list()
while number > 0:
res.append(number % 256)
number //= 256
return bytes(res[::-1])
block_size = 512
msg = 'The quick brown fox jumps over the lazy dog'
key = 'key'
ipad = 54
opad = 92
block_ipad, block_opad = calculate_ipad_opad(block_size, ipad, opad)
key_decimal = string_to_decimal(key)
si = key_decimal ^ block_ipad
so = key_decimal ^ block_opad
a = sha256(integer_to_bytes(so) + sha256(integer_to_bytes(si) + msg.encode()).digest())
print(a.digest())
我知道密钥长度不超过块大小。我使用 Wikipedia 编写代码。但它不能正常工作。你能帮我解决一下吗???
编辑:
我预计代码的输出为 f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8
。但是输出是 3d6243123b984bcc17cb96eb61c2b47d27545c3a9119b623be7932e846bf0643
.
键的右侧必须用 0x00 值填充到摘要的块大小(如果键大小小于块大小,这里就是这种情况)。您可以通过例如在 return
:
string_to_decimal()
res = res.ljust(64 * 2, "0")
通过此更改,提供了预期的结果。
对于实现,最好使用更详细的算法规范,例如FIPS PUB 198-1 instead of the highly abbreviated description in Wikipedia. Furthermore, you are on the safe side if official test vectors 已应用。
实际上不需要转换为十进制数,即可以像对象一样直接使用字节,这大大简化了实现:
from hashlib import sha256
msg = 'The quick brown fox jumps over the lazy dog'
key = 'key'
block_size_bytes = 64
block_opad_bytes = b'\x5c' * block_size_bytes
block_ipad_bytes = b'\x36' * block_size_bytes
key_bytes = key.encode().ljust(block_size_bytes, b'[=11=]')
si_bytes = bytes([a ^ b for (a, b) in zip(block_ipad_bytes, key_bytes)])
so_bytes = bytes([a ^ b for (a, b) in zip(block_opad_bytes, key_bytes)])
a = sha256(so_bytes + sha256(si_bytes + msg.encode()).digest())
print(a.digest().hex()) # f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8