from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, hmac
def pythons_sha256_hmac(text: bytes, k: bytes) -> bytes:
h = hmac.HMAC(k, hashes.SHA256(), backend=default_backend())
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
cryptographylibrary’s implementation. Ensure that they produce the same outputs!
Python’s HMAC
official_result = pythons_sha256_hmac(text=b'hello world', k=b'accccc').hex(sep=' ')
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
BLOCK_SIZE_OF_SHA256 = 64 # bytes
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):
result.append(_1 ^ _2)
return bytes(result)
def custom_hmac(key: bytes, text: bytes) -> bytes:
key = make_key_B_bytes_long(key=key)
ipad = bytes.fromhex('36') * BLOCK_SIZE_OF_SHA256
opad = bytes.fromhex('5c') * BLOCK_SIZE_OF_SHA256
kipad = xor_two_byte_strings(key, ipad)
kopad = xor_two_byte_strings(key, opad)
return h(kopad + h(kipad + text))custom_result = custom_hmac(text=b'hello world', key=b'accccc').hex(sep=' ')
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