from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, hmac
def pythons_sha256_hmac(text: bytes, k: bytes) -> bytes:
= hmac.HMAC(k, hashes.SHA256(), backend=default_backend())
h
h.update(text) return h.finalize()
5.5 TEST PYTHON’S HMAC
EXERCISE 5.5 TEST PYTHON’S HMAC
Although you should not roll your own crypto, it doesn’t mean you shouldn’t verify implementations! Create your own implementation of HMAC following the instructions from RFC 2104 and test some inputs and keys with both your implementation and Python’s
cryptography
library’s implementation. Ensure that they produce the same outputs!
Python’s HMAC
= pythons_sha256_hmac(text=b'hello world', k=b'accccc').hex(sep=' ')
official_result print(official_result)
ae 7d 07 10 49 9d 66 48 ce 14 71 95 f7 96 06 a7 02 74 a2 93 34 67 0b 4a f5 18 f7 99 10 d6 f4 b0
Custom HMAC
from hashlib import sha256
= 64 # bytes
BLOCK_SIZE_OF_SHA256
def h(x: bytes) -> bytes: return sha256(x).digest()
def make_key_B_bytes_long(key: bytes):
if len(key) == BLOCK_SIZE_OF_SHA256:
return key
elif len(key) < BLOCK_SIZE_OF_SHA256:
return key + bytes(BLOCK_SIZE_OF_SHA256 - len(key))
else:
return make_key_B_bytes_long(h(key))
# the following function is taken from Exercise 3.9.
def xor_two_byte_strings(x: bytes, y: bytes) -> bytes:
assert (len(x) == len(y))
= []
result for _1, _2 in zip(x, y):
^ _2)
result.append(_1 return bytes(result)
def custom_hmac(key: bytes, text: bytes) -> bytes:
= make_key_B_bytes_long(key=key)
key = bytes.fromhex('36') * BLOCK_SIZE_OF_SHA256
ipad = bytes.fromhex('5c') * BLOCK_SIZE_OF_SHA256
opad = xor_two_byte_strings(key, ipad)
kipad = xor_two_byte_strings(key, opad)
kopad
return h(kopad + h(kipad + text))
= custom_hmac(text=b'hello world', key=b'accccc').hex(sep=' ')
custom_result print(custom_result)
ae 7d 07 10 49 9d 66 48 ce 14 71 95 f7 96 06 a7 02 74 a2 93 34 67 0b 4a f5 18 f7 99 10 d6 f4 b0
print(custom_result == official_result)
True