2
\$\begingroup\$

I wanted to understand the HMAC algorithm. So, I implemented it as a Jupyter Notebook with all intermediate steps being output to console. My objective now is to improve it so it may serve as a reference to anyone trying to implement or understand it.

The Jupyter Notebook on github is easier to read and I would like feedback on the notebook rather than the code below.

Jupiter notebook on GitHub

import hashlib
import hmac

### Define key, message, Block size, hashing algorithm    
hash_algo = "sha1"
B = 64
message = b'hello!'
key = b'key'

### hash () for an easy to read code
def hash(M):
    H = hashlib.new(hash_algo)
    H.update(M)
    b_hash = H.digest()
    return b_hash

### XOR Translation table
trans_5C = bytes((x ^ 0x5C) for x in range(256))
trans_36 = bytes((x ^ 0x36) for x in range(256))

### Zero pad key to block length B
K_zpad=key.ljust(B,b'\0')
# Xor with ipad and opad sequence
K_ipad=K_zpad.translate(trans_36)
K_opad=K_zpad.translate(trans_5C)

print("Key XOR ipad(0x363636...):\n"+K_ipad.hex())
print("\n\nKey XOR opad(0x505050...):\n"+K_opad.hex())

### concatinate message
part1=K_ipad+message
print("key XOR ipad || message:\n"+part1.hex())

### hash (key xor ipad || message )
hash1=hash(part1)
print("hash( key XOR ipad || message):\n"+hash1.hex())

### hash (key xor opad || hash ( (key xor ipad)||message ) )
part2 = K_opad + hash1
print("hash (key xor opad || hash ( (key XOR ipad)||message ) ):\n"+part2.hex())
hash_final = hash(part2)
print("\n\nFinal Hash:\n"+hash_final.hex())

# Compare with Python's HMAC Implementation
pyH=hmac.new(key,message,digestmod=hash_algo)
pyH.hexdigest()
\$\endgroup\$
1
\$\begingroup\$

My objective now is to improve it so it may serve as a reference to anyone trying to implement or understand it.

In light of that goal I would have thought it made more sense to use the documented test vectors of RFC 2202 rather than make up your own one.


### hash (key xor opad || hash ( (key xor ipad)||message ) )
part2 = K_opad + hash1
print("hash (key xor opad || hash ( (key XOR ipad)||message ) ):\n"+part2.hex())
hash_final = hash(part2)
print("\n\nFinal Hash:\n"+hash_final.hex())

The comment and the first print describe hash_final, not part2. IMO this is a bug, albeit a minor one.

\$\endgroup\$
  • \$\begingroup\$ hash_final = hash(part2) what is wrong? The comment and print are expanding the part1 in part2 as hash ( (key xor ipad)||message \$\endgroup\$ – Lord Loh. Aug 20 '18 at 14:22
  • \$\begingroup\$ @LordLoh., what's wrong is print("hash ( \$\endgroup\$ – Peter Taylor Aug 20 '18 at 14:23
  • \$\begingroup\$ I see. Thank you. I was unaware of RFC 2202. That is a good idea! \$\endgroup\$ – Lord Loh. Aug 20 '18 at 14:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.