Python中的HMAC SHA256: HMAC库与Hashlib生成不同结果

3

我一直在查看维基百科上HMAC的伪代码,它似乎相对简单;如果您的密钥长度已经等于块大小,那么伪代码就可以简化为3行:

    o_key_pad  key xor [0x5c * blockSize]   // Outer padded key
    i_key_pad  key xor [0x36 * blockSize]   // Inner padded key

    return hash(o_key_pad  hash(i_key_pad  message))

这个可以很容易地翻译成Python:

ik = bytes([0x36 ^ b for b in k])
ok = bytes([0x5c ^ b for b in k])

print(hashlib.sha256(ok + bytearray.fromhex(hashlib.sha256(ik+msg).hexdigest())).hexdigest())

但这与使用Python的HMAC库不会产生相同的结果:
p = bytes("password", encoding='utf8')
k = bytearray.fromhex("eae1f9b8c78d0e0dbaeb3bc49fea3f0be9e9dc580c0b0ba09bcf5104713fda80")

x = hmac.new(k, digestmod='sha256')
x.update(p)
print(x.hexdigest())

ik = bytes([0x36 ^ b for b in k])
ok = bytes([0x5c ^ b for b in k])
print(hashlib.sha256(ok + bytearray.fromhex(hashlib.sha256(ik+p).hexdigest())).hexdigest())

最终会产生

1b96a6d3473698c3592a99d752934b875f82cdd623230abc534f92e7b70cc251 57dcbe4ada890bcc8d3cc2e6072874e0d1a0d6d3f73ceb1ced8dad4f07b56e33

为什么?

1个回答

2
在自定义实现中,密钥填充到块大小的填充方式缺失,请参见此处

长度小于块大小的密钥通过在右侧用零进行填充来填充到块大小

SHA256的块大小为64字节,详见此处
以下Python代码可生成预期结果:
import hmac 
import hashlib

p = bytes("password", encoding='utf8')
k = bytearray.fromhex("eae1f9b8c78d0e0dbaeb3bc49fea3f0be9e9dc580c0b0ba09bcf5104713fda80")

x = hmac.new(k, digestmod='sha256')
x.update(p)
print(x.hexdigest())

k = bytearray.fromhex("eae1f9b8c78d0e0dbaeb3bc49fea3f0be9e9dc580c0b0ba09bcf5104713fda80".ljust(128,'0')) # pad with zeros
ik = bytes([0x36 ^ b for b in k])
ok = bytes([0x5c ^ b for b in k])
print(hashlib.sha256(ok + bytearray.fromhex(hashlib.sha256(ik+p).hexdigest())).hexdigest())

输出结果为:

1b96a6d3473698c3592a99d752934b875f82cdd623230abc534f92e7b70cc251
1b96a6d3473698c3592a99d752934b875f82cdd623230abc534f92e7b70cc251

这也可以在这里进行验证。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接