Reputation: 193
So I've been looking at Wikipedia's pseudocode for HMAC and it seemed relatively straightforward; if your key size is already the block size, the pseudo code boils down to 3 lines:
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))
This translates very easily into 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())
But this doesn't produce the same result as using Python's HMAC library:
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())
ends up producing
1b96a6d3473698c3592a99d752934b875f82cdd623230abc534f92e7b70cc251 57dcbe4ada890bcc8d3cc2e6072874e0d1a0d6d3f73ceb1ced8dad4f07b56e33
Why?
Upvotes: 3
Views: 998
Reputation: 49460
In the custom implementation the padding of the key to the block size is missing, see here:
Keys shorter than blockSize are padded to blockSize by padding with zeros on the right
The block size of SHA256 is 64 bytes, see here.
The following ptyhon code produces the expected result:
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())
with the output:
1b96a6d3473698c3592a99d752934b875f82cdd623230abc534f92e7b70cc251
1b96a6d3473698c3592a99d752934b875f82cdd623230abc534f92e7b70cc251
which can also be verified here.
Upvotes: 2