Updated On : Feb-20,2021 Tags hmac, message-authentication-codes
hmac - Hash-based Message Authentication Code using Python

hmac - Hash-based Message Authentication Code using Python

The HMAC is an algorithm that generates a hash of the message using a cryptographic hash function and a secret cryptographic key. It can be used to check data for integrity and authenticity. It lets us calculate message authenticity and integrity using a shared key between two parties without the use of complex public key infrastructure involving certificates. Python provides us with module name hmac which provides an implementation for this algorithm. It takes as input hashing algorithm name which is one of the algorithms which is available through hashlib library of Python. As a part of this tutorial, we'll explain with simple examples how we can generate message authentication code using hmac module of Python.

Below we have printed names of the algorithms available through hashlib library. If you are interested in learning about hashlib library then please feel free to check our tutorial on the same.

In [2]:
import hashlib

print("List of Available Algorithms to Construct Secure Hash/Message Digest : {}".format(hashlib.algorithms_available))
print("\nList of Algorithms Guaranteed to Work : {}".format(hashlib.algorithms_guaranteed))
print("\nList of Algorithms that May Work : {}".format(hashlib.algorithms_available.difference(hashlib.algorithms_guaranteed)))
List of Available Algorithms to Construct Secure Hash/Message Digest : {'sha3-256', 'whirlpool', 'sha3_512', 'ripemd160', 'sha3_384', 'sha3-512', 'sha512-224', 'sm3', 'md4', 'sha3-224', 'sha1', 'sha3_224', 'sha384', 'shake_256', 'blake2s256', 'sha512-256', 'sha3_256', 'blake2b512', 'sha3-384', 'blake2b', 'shake256', 'shake128', 'md5-sha1', 'sha512', 'blake2s', 'md5', 'mdc2', 'sha256', 'sha224', 'shake_128'}

List of Algorithms Guaranteed to Work : {'md5', 'sha1', 'sha3_224', 'sha384', 'sha3_256', 'sha3_512', 'shake_256', 'sha3_384', 'sha256', 'blake2b', 'sha224', 'shake_128', 'sha512', 'blake2s'}

List of Algorithms that May Work : {'sha3-256', 'sha3-224', 'whirlpool', 'mdc2', 'ripemd160', 'blake2b512', 'sha3-384', 'md5-sha1', 'md4', 'shake256', 'sha3-512', 'shake128', 'blake2s256', 'sha512-224', 'sha512-256', 'sm3'}

Example 1

As a part of our first example, we'll explain how we can generate a message authentication code of a given message based on the input key and secure hashing algorithm using hmac module.


  • new(key,message=None,digestmod='') - This constructor creates an instance of HMAC with initial message given as bytes. It can be then used to generate message authentication code. We can only create an instance of HMAC as well without any initial message but we'll need key and digestmod. We can add messages using a call to update() method. The key needs to be in bytes format. The digestmod parameter accepts secure hashing algorithm names that are available through hashlib module (We have printed their names above).

Important Methods of HMAC Instance

  • update(message_bytes) - This method adds messages given as input to already an existing message. We can call this method more than once and it'll keep on adding up messages.

  • digest() - It returns the message authentication code of the data in bytes format. The size of the output is dependent on the input secure hashing algorithm. For example, if the input hashing algorithm is SHA1, then the output will be 20 bytes.

  • hexdigest() - It returns message authentication code of data as hexadecimal digits. The hexadecimal digest will be twice the size of bytes digest because one byte can represent two hexadecimal digits. The size of the output is dependent on the input secure hashing algorithm. For example, if the input hashing algorithm is SHA1, then the output will be 40 hexadecimal digits.

Important Attributes of HMAC Instance

  • digest_size - It returns an integer representing the number of bytes of secure hash that the algorithm will generate.
  • block_size - It returns an integer value representing the block size of the algorithm. The secure hash algorithms divide data into blocks where each block contains a number of bytes of data on which algorithm will work.

Our code for this example starts by initializing the message and key. It then generates message authentication code for the given message using key and sha1 algorithm in three different ways.

We first create an instance of HMAC using new() method by giving it key and message as bytes and hashing algorithm name as sha1. We are then printing message authentication code.

Our second part of the code creates the HMAC instance without any initial message. It then uses update() method to add message. At last, it calculates digest and prints it.

Our third part of the code creates an instance of HMAC without any initial message. It then adds messages in two parts using update() method. At last, it calculates digest and prints it.

The code at last prints digest size and block size for each HMAC instance.

In [29]:
import hmac

message = "Welcome to CoderzColumn."
key= "abracadabra"

########## 1 ##################
hmac1 = hmac.new(key=key.encode(), msg=message.encode(), digestmod="sha1")
message_digest1 = hmac1.digest()

print("{} - Message Digest 1 : {}".format(hmac1.name, message_digest1))

########## 2 ##################
hmac2 = hmac.new(key=key.encode(), digestmod="sha1")
hmac2.update(bytes(message, encoding="utf-8"))
message_digest2 = hmac2.digest()

print("{} - Message Digest 2 : {}".format(hmac2.name, message_digest2))

########## 3 ##################
hmac3 = hmac.new(key=key.encode(), digestmod="sha1")
hmac3.update(bytes("Welcome to ", encoding="utf-8"))
hmac3.update(bytes("CoderzColumn.", encoding="utf-8"))
message_digest3 = hmac3.digest()

print("{} - Message Digest 3 : {}".format(hmac3.name, message_digest3))


print("\nMessage Digest Size for 1 : {}, 2 : {} and 3 : {}".format(hmac1.digest_size, hmac2.digest_size,hmac3.digest_size,))
print("Message Block  Size for 1 : {}, 2 : {} and 3 : {}".format(hmac1.block_size, hmac2.block_size,hmac3.block_size,))
hmac-sha1 - Message Digest 1 : b'@\xbdC[\x1d\x8c\xdf\n\xb0[\x9d\x86jc\xa9\xba\x862\x9c\x1a'
hmac-sha1 - Message Digest 2 : b'@\xbdC[\x1d\x8c\xdf\n\xb0[\x9d\x86jc\xa9\xba\x862\x9c\x1a'
hmac-sha1 - Message Digest 3 : b'@\xbdC[\x1d\x8c\xdf\n\xb0[\x9d\x86jc\xa9\xba\x862\x9c\x1a'

Message Digest Size for 1 : 20, 2 : 20 and 3 : 20
Message Block  Size for 1 : 64, 2 : 64 and 3 : 64

Example 2

As a part of our second example, we are explaining how we can calculate message authentication code using HMAC algorithm again but this time we have used SHA256 secure hashing algorithm inside of it.

Our code for this part is exactly the same as our previous example but with minor changes. It uses a reference to SHA256 algorithm available through hashlib library.

In [28]:
import hmac

message = "Welcome to CoderzColumn."
key= "abracadabra"

########## 1 ##################
hmac1 = hmac.new(key=key.encode(), msg=message.encode(), digestmod=hashlib.sha256)
message_digest1 = hmac1.digest()

print("{} - Message Digest 1 : {}".format(hmac1.name, message_digest1))

########## 2 ##################
hmac2 = hmac.new(key=key.encode(), digestmod=hashlib.sha256)
hmac2.update(bytes(message, encoding="utf-8"))
message_digest2 = hmac2.digest()

print("{} - Message Digest 2 : {}".format(hmac2.name, message_digest2))

########## 3 ##################
hmac3 = hmac.new(key=key.encode(), digestmod=hashlib.sha256)
hmac3.update(bytes("Welcome to ", encoding="utf-8"))
hmac3.update(bytes("CoderzColumn.", encoding="utf-8"))
message_digest3 = hmac3.digest()

print("{} - Message Digest 3 : {}".format(hmac3.name, message_digest3))


print("\nMessage Digest Size for 1 : {}, 2 : {} and 3 : {}".format(hmac1.digest_size, hmac2.digest_size,hmac3.digest_size,))
print("Message Block  Size for 1 : {}, 2 : {} and 3 : {}".format(hmac1.block_size, hmac2.block_size,hmac3.block_size,))
hmac-sha256 - Message Digest 1 : b')\x08\xc2\xfe\x9en\xc4k\xfd\x9c\xc8\xef\xa6*}\xc7\xf7h\xe9\xa4\x88\x19u\xfe\x9d\x834J\xdd\x13\xf5\x12'
hmac-sha256 - Message Digest 2 : b')\x08\xc2\xfe\x9en\xc4k\xfd\x9c\xc8\xef\xa6*}\xc7\xf7h\xe9\xa4\x88\x19u\xfe\x9d\x834J\xdd\x13\xf5\x12'
hmac-sha256 - Message Digest 3 : b')\x08\xc2\xfe\x9en\xc4k\xfd\x9c\xc8\xef\xa6*}\xc7\xf7h\xe9\xa4\x88\x19u\xfe\x9d\x834J\xdd\x13\xf5\x12'

Message Digest Size for 1 : 32, 2 : 32 and 3 : 32
Message Block  Size for 1 : 64, 2 : 64 and 3 : 64

Example 3

As a part of our third example, we are explaining how we can generate hex message authentication code using HMAC algorithm with SHA256 as its back end.

Our code for this example is exactly the same as our previous example with the only change that we are calling hexdigest() method to calculate hexadecimal authentication code.

In [31]:
import hmac

message = "Welcome to CoderzColumn."
key= "abracadabra"

########## 1 ##################
hmac1 = hmac.new(key=key.encode(), msg=message.encode(), digestmod=hashlib.sha256)
message_digest1 = hmac1.hexdigest()

print("{} - Hex Message Digest 1 : {}".format(hmac1.name, message_digest1))

########## 2 ##################
hmac2 = hmac.new(key=key.encode(), digestmod=hashlib.sha256)
hmac2.update(bytes(message, encoding="utf-8"))
message_digest2 = hmac2.hexdigest()

print("{} - Hex Message Digest 2 : {}".format(hmac2.name, message_digest2))

########## 3 ##################
hmac3 = hmac.new(key=key.encode(), digestmod=hashlib.sha256)
hmac3.update(bytes("Welcome to ", encoding="utf-8"))
hmac3.update(bytes("CoderzColumn.", encoding="utf-8"))
message_digest3 = hmac3.hexdigest()

print("{} - Hex Message Digest 3 : {}".format(hmac3.name, message_digest3))


print("\nMessage Digest Size for 1 : {}, 2 : {} and 3 : {}".format(hmac1.digest_size, hmac2.digest_size,hmac3.digest_size,))
print("Message Block  Size for 1 : {}, 2 : {} and 3 : {}".format(hmac1.block_size, hmac2.block_size,hmac3.block_size,))
hmac-sha256 - Hex Message Digest 1 : 2908c2fe9e6ec46bfd9cc8efa62a7dc7f768e9a4881975fe9d83344add13f512
hmac-sha256 - Hex Message Digest 2 : 2908c2fe9e6ec46bfd9cc8efa62a7dc7f768e9a4881975fe9d83344add13f512
hmac-sha256 - Hex Message Digest 3 : 2908c2fe9e6ec46bfd9cc8efa62a7dc7f768e9a4881975fe9d83344add13f512

Message Digest Size for 1 : 32, 2 : 32 and 3 : 32
Message Block  Size for 1 : 64, 2 : 64 and 3 : 64

Example 4

As a part of our code, we are explaining how we can generate message authentication code using digest() method of the hmac module without creating an instance of the HMAC.


  • digest(key,msg,digest) - It accepts key, message to encode and digest algorithm as input and generates message authentication code for given input message.

Our code for this example, explains how we can digest() method to generate message authentication code for the given message using input key directly without creating an instance of HMAC instance like the previous example. This method works fast compared to creating authentication code for small messages through HMAC instance because it uses optimized C implementation for creating digest.

In [35]:
import hmac

message = "Welcome to CoderzColumn."
key= "abracadabra"

########## 1 ##################
message_digest1 = hmac.digest(key=key.encode(), msg=message.encode(), digest="sha3_256")

print("Message Digest 1 : {}".format(message_digest1))

########## 2 ##################
message_digest2 = hmac.digest(key=key.encode(), msg=bytes(message, encoding="utf-8"), digest=hashlib.sha3_256)

print("Message Digest 2 : {}".format(message_digest2))
Message Digest 1 : b';\x84\x14\xf7Z\xef\x10\t\xbd\xa0w\xa7\xd1\xc6\xf7&\xe8\x86\xff\xfa\x90\x9d\x82V\xc0\xa4Qeeq.\x8f'
Message Digest 2 : b';\x84\x14\xf7Z\xef\x10\t\xbd\xa0w\xa7\xd1\xc6\xf7&\xe8\x86\xff\xfa\x90\x9d\x82V\xc0\xa4Qeeq.\x8f'

Example 5

As a part of our fifth example, we are explaining how we can use compare() method of hmac module to compare message authentication codes.


  • compare(a,b) - This function compares two message authentication codes and returns True if they are equal else False. This function helps us prevent timing analysis attacks which can help attackers know the size of the message authentication code.

Our code for this example creates two message authentication codes and compares them using compare() method.

In [36]:
import hmac

message = "Welcome to CoderzColumn."
key= "abracadabra"

########## 1 ##################
message_digest1 = hmac.digest(key=key.encode(), msg=message.encode(), digest="sha3_256")

print("Message Digest 1 : {}".format(message_digest1))

########## 2 ##################
message_digest2 = hmac.digest(key=key.encode(), msg=bytes(message, encoding="utf-8"), digest=hashlib.sha3_256)

print("Message Digest 2 : {}".format(message_digest2))

print("\nIs message digest 1 is equal to message digest 2? : {}".format(hmac.compare_digest(message_digest1, message_digest2)))
Message Digest 1 : b';\x84\x14\xf7Z\xef\x10\t\xbd\xa0w\xa7\xd1\xc6\xf7&\xe8\x86\xff\xfa\x90\x9d\x82V\xc0\xa4Qeeq.\x8f'
Message Digest 2 : b';\x84\x14\xf7Z\xef\x10\t\xbd\xa0w\xa7\xd1\xc6\xf7&\xe8\x86\xff\xfa\x90\x9d\x82V\xc0\xa4Qeeq.\x8f'

Is message digest 1 is equal to message digest 2? : True

This ends our small tutorial explaining how we can create a message authentication code for a given message using hmac module. Please feel free to let us know your views in the comments section.



Sunny Solanki  Sunny Solanki