Table of Contents
HMAC (RFC 2104) has been implemented in Python. The SHA-256 library was used for the hash function.
Overview of HMAC
HMAC is a cryptographic technique used to generate a Message Authentication Code (MAC) for authentication of the sender and detection of message tampering. HMAC combines a hash function with a secret key to produce the MAC.
HMAC has the following features:
- It generates the MAC by depending on both the secret key and the message, so someone who doesn’t know the secret key cannot compute the same MAC. This allows for sender authentication.
- By applying the hash function twice, it significantly reduces the probability of the MAC matching even if a part of the message is changed. This enhances the ability to detect message tampering.
- HMAC can use any hash function. For example, hash functions like SHA-256 or MD5 can be applied to HMAC.
- HMAC is an irreversible cryptographic technique.
Procedure Explanation
The procedures are meticulously described in RFC 2104.
What HMAC requires is the hash function H and the secret key K.
Let’s denote the block length of hash function H as B bytes and the output length as L bytes. For the hash function H = SHA-256, B = 64, L = 32.
Although K is referred to as a secret key, it doesn’t necessarily have to be the private key in public-key cryptography. It just needs to be a secret string unknown to others. RFC 2104 specifies that the length of K should be at least the output length of the hash function. Since K performs bitwise operations with the hash value, if it’s shorter than the hash value, it needs to be padded with the specified value to avoid being easily guessed.
The flow of HMAC calculation is as follows:
- If the secret key K is longer than the hash function’s block length B, convert K to an L-byte hash value using the hash function. Use the generated hash value as the secret key K for HMAC.
- If the secret key K is shorter than the hash function’s block length B, append zeros (
0x00
) to the end of K to make it B bytes in total. - Compute the XOR of the above result and the value repeated B times (
ipad = b'\x36' * B
). This is a bitwise operation. - Append the encrypted message (bit array) to the above result.
- Convert the above result to a hash value using the hash function H.
- Compute the XOR of the secret key and the value repeated B times (
opad = b'\x5c' * B
). This is a bitwise operation. - Append the calculated hash value to the XOR obtained above.
- Convert the above result to a hash value using the hash function H.
Program
And here is the HMAC (SHA-256) implemented in Python:
Environment
- Python 3.10.13
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# HMAC with SHA-256 def sha256(message): # SHA-256 implementation import hashlib return hashlib.sha256(message).digest() def xor(a, b): # XOR two byte strings return bytes([x ^ y for x, y in zip(a, b)]) def hmac_sha256(key, message): """ HMAC-SHA256 implementation >>> text = b"Hi There" >>> key = b'\x0b' * 20 >>> a = hmac_sha256(key, text).hex() >>> import hmac >>> b = hmac.new(key, text.encode('ascii'), hashlib.sha256).digest().hex() >>> a == b True >>> text = b"Hello" * 100 >>> key = b'1234567890' * 100 >>> a = hmac_sha256(key, text).hex() >>> import hmac >>> b = hmac.new(key, text.encode('ascii'), hashlib.sha256).digest().hex() >>> a == b True :param key: :param message: :return: """ if len(key) > 64: key = sha256(key) if len(key) < 64: key = key + b'\x00' * (64 - len(key)) o_key_pad = xor(b'\x5c' * 64, key) i_key_pad = xor(b'\x36' * 64, key) return sha256(o_key_pad + sha256(i_key_pad + message)) if __name__ == '__main__': import hmac import hashlib |
Alternative Methods for MAC Generation Besides HMAC
Besides HMAC, there are other methods to generate a MAC using the Keccak hash function called KMAC and using any block cipher called CMAC.