How to create and verify HMAC with openssl

Main picture of the post: How to create and verify HMAC with openssl

The HMAC stands for “Hash-based Message Authentication Code” and it could be based on the previous hash functions explained before to calculate it. It serves for integrity and authentication of a message when using symmetric encryption or any shared secret communication scheme based.

It was published in 1996 and the outcome of the function depends on the hash algorithm used. Therefore, if SHA1 or SHA256 is used for HMAC, the naming of the operation is HMAC-SHA1 or HMAC-SHA256 respectively.

To compute the HMAC, it performs 2 iterations of hashing operations and it is based in the message/data sent (Encrypted previously or not), the shared secret or symmetric key used for encrypting the message which is derived into 2 different keys (inner and outer key). Next, this resulting HMAC operation is appended to the message and sent to the receiver who will repeat the same operations with the message received and the shared secret, with the sake of obtaining the same HMAC value.

Picture of a diagram that shows how HMAC is calculated
HMAC Calculation diagram

Note that, HMAC can be computed from the message in clear or encrypted form and it will work in both cases without any flaws. Nevertheless, there’s an important difference in terms of operations that you may want to consider.

If HMAC is done over the encrypted message, the receiver will perform the HMAC validation before the decryption. So, if the message is not valid, then the receiver will not continue with the decryption operation saving some computing resources. However, if it is done over the clear text, the receiver will need to do the decryption first and then calculate the HMAC afterwards. Then, if the validation is failed then the decryption operation was performed in vain wasting computing resources. That’s an important efficiency fact that should not be overlooked when designing this type of secure communications.

A simple encryption with HMAC use case

Let’s perform a simple use case example where the user Alice wants to send a file securely with HMAC to Bob, who will perform a message authentication verification, in order to ensure that the encrypted message comes from the same shared secret.

In addition, to simplify the process, let’s assume that both Alice and Bob already did the key exchange and both have in possession the shared secret.

Then, Alice first will create the file that she wants to share with Bob and then encrypts it with openssl as it shows in the next example.

$ echo "Hello World" > hello_world.txt
$ openssl enc -aes-256-cbc -p -pbkdf2 -iter 310000 -md sha256 -salt -in hello_world.txt -out encrypted | grep "^key=" | cut -d= -f2 > shared_secret

The “shared_secret” file contains the symmetric key used to encrypt the hello_world.txt file.

Afterwards, Alice generates the HMAC-SHA256 with the encrypted message (Can be done also with plain text message) and the “shared_secret” helped with openssl:

$ openssl dgst -hmac $(cat shared_secret) -sha256 encrypted 
HMAC-SHA256(encrypted)= 8230b50b02233a786ca779628ddc8137169f55322abd12b6698c7f76c3311a3b
$ openssl dgst -hmac $(cat shared_secret) -sha256 hello_world.txt 
HMAC-SHA256(hello_world.txt)= 9fdd6074bde72da381804c07fe600a7b77f1996c15d5fbca90290fee0a4585da

Next, she sends the encrypted message to Bob alongside with the HMAC-SHA256 calculated in the last step.

Once the encrypted message and HMAC-SHA256 value is received by Bob, he proceeds to do the validation by repeating the same last step done by Alice to obtain by himself the HMAC-SHA256 and then compare it with the received one. If both are exactly the same then the validation passes. Otherwise it will fail.

Nevertheless, if the HMAC was created with the message in clear, the first validation will fail and he will need to decrypt the message first before validating it:

$ openssl enc -aes-256-cbc -d -pbkdf2 -iter 310000 -md sha256 -salt -in encrypted -out decrypted
enter aes-256-cbc decryption password:
$ cat decrypted 
Hello World
$ openssl dgst -hmac $(cat shared_secret) -sha256 decrypted
HMAC-SHA256(decrypted)= 9fdd6074bde72da381804c07fe600a7b77f1996c15d5fbca90290fee0a4585da

As you may notice, the last example is showing that the HMAC calculated by Bob from the decrypted message corresponds to the one calculated with “hello_world.txt” file that came from Alice. Hence, the validation is passed.