如何在不使用 hmac 库的情况下在 python 中实现 HMAC?
How to implement HMAC in python without using the hmac library?
我想根据 RFC 2104 的定义使用 SHA-1 实现 hmac 算法。代码是 运行 但结果与 test-vectors from RFC 不同。我不确定我是否正确加载了值(字符串到十六进制,还是字符串到字节?)。
作为模板,我使用了 wikipedia
中的伪代码
我不确定 'blocksize' 和 'output size' 这两个词。在维基百科的代码中,outputsize 是输入值之一,但从未使用过。
到目前为止,这是我的代码:
首先,我设置了一个散列函数,然后将我的输入字符串(键和消息)转换为十六进制值。下一步是查看密钥是否已被散列或填充为零。接下来,我将键中的单个字符与这些值进行异或运算(我不知道它们来自哪里,但它们在每个示例中都没有任何评论)。最后但并非最不重要的一点是,我正在组合一个内部字符串(I_key_pad + 消息)并对其进行哈希处理,这会导致一个外部字符串与外部垫组合并再次对其进行哈希处理。
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'[=11=]') #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()
我不理解您代码中的所有步骤,但这里有一个简短的示例,显示仅使用 hashlib.sha1
的 HMAC-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
我想根据 RFC 2104 的定义使用 SHA-1 实现 hmac 算法。代码是 运行 但结果与 test-vectors from RFC 不同。我不确定我是否正确加载了值(字符串到十六进制,还是字符串到字节?)。
作为模板,我使用了 wikipedia
中的伪代码我不确定 'blocksize' 和 'output size' 这两个词。在维基百科的代码中,outputsize 是输入值之一,但从未使用过。
到目前为止,这是我的代码: 首先,我设置了一个散列函数,然后将我的输入字符串(键和消息)转换为十六进制值。下一步是查看密钥是否已被散列或填充为零。接下来,我将键中的单个字符与这些值进行异或运算(我不知道它们来自哪里,但它们在每个示例中都没有任何评论)。最后但并非最不重要的一点是,我正在组合一个内部字符串(I_key_pad + 消息)并对其进行哈希处理,这会导致一个外部字符串与外部垫组合并再次对其进行哈希处理。
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'[=11=]') #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()
我不理解您代码中的所有步骤,但这里有一个简短的示例,显示仅使用 hashlib.sha1
的 HMAC-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