Message Authentication with HMAC in Cryptography

LinuxBeginner
Practice Now

Introduction

In the world of digital communication, it's crucial to ensure that messages are not only kept private but also that they haven't been tampered with during transit (integrity) and that they truly come from the claimed sender (authenticity). While simple hash functions can check for accidental data corruption, they can't prevent malicious tampering, as anyone can re-compute the hash of a modified message.

This is where HMAC (Hash-based Message Authentication Code) comes in. HMAC is a specific type of Message Authentication Code (MAC) that combines a cryptographic hash function (like SHA-256) with a secret key. Only parties who possess the secret key can generate and verify the HMAC for a given message. This process provides both data integrity and authenticity.

In this lab, you will get hands-on experience with HMAC. You will start by understanding the concept, then use the powerful openssl command-line tool to generate keys and compute HMACs. Finally, you will see how to implement HMAC in a Python script, a common task in application development.

Introduction to HMAC

In this step, we will cover the fundamental concept of HMAC and why it is essential for secure communication.

A standard hash function, like SHA-256, takes an input message and produces a fixed-size string of characters, known as a hash or digest. If even a single bit of the message changes, the resulting hash will be completely different. This is great for checking data integrity. However, it does not provide authenticity. If an attacker intercepts and modifies a message, they can simply compute a new hash for the tampered message and send it along. The receiver would have no way of knowing the message was altered.

HMAC solves this problem by introducing a secret symmetric key into the hashing process. A symmetric key is a piece of secret information shared only between the sender and the intended receiver.

The HMAC process works roughly as follows:

  1. The sender combines the secret key with the message.
  2. A hash function (e.g., SHA-256) is applied to this combination.
  3. The resulting hash, now called the HMAC, is sent along with the original message.

When the receiver gets the message and the HMAC, they perform the same calculation using their copy of the secret key.

  • If the calculated HMAC matches the received HMAC, the receiver knows the message has not been altered (integrity) and it came from someone who has the secret key (authenticity).
  • If the HMACs do not match, the message is considered compromised and should be discarded.

This step is purely conceptual. In the following steps, you will put this theory into practice.

Generate HMAC Secret Key

In this step, you will generate a secure, random secret key which is the foundation of HMAC's security. A predictable key would allow an attacker to forge HMACs. We will use the openssl tool, a versatile cryptography command-line utility.

We will use the openssl rand command to generate random data.

  • -hex: This option tells openssl to output the random data as a hexadecimal string.
  • 32: This specifies the number of random bytes to generate. 32 bytes is equivalent to 256 bits, which is a strong and commonly used key length, especially when paired with the SHA-256 hash algorithm.

To make the key easy to use in subsequent commands, we will generate it and store it in an environment variable named HMAC_KEY. Run the following command in your terminal:

export HMAC_KEY=$(openssl rand -hex 32)

This command executes openssl rand -hex 32, and its output (the hex key) is captured and assigned to the HMAC_KEY variable.

You can view the key you just generated by using the echo command:

echo $HMAC_KEY

You should see a long string of hexadecimal characters. Your key will be unique.

0db348c78473ce8460416f875cd87239d0f5f66fbe5103ba4b5c84cf2cd76914

Now that you have a secret key, you are ready to create an HMAC.

Compute HMAC-SHA256

In this step, you will compute an HMAC for a sample message using the key you generated. First, let's create a file containing our message.

We will use the echo command to create a file named message.txt. The -n flag is important as it prevents echo from adding a newline character at the end of the string, which would alter the content and thus the final HMAC.

echo -n "This is a secret message." > message.txt

Now, with the message and the key, we can compute the HMAC. We will use the openssl dgst command, which is used for calculating message digests (hashes).

  • -sha256: Specifies that we want to use the SHA-256 hash algorithm.
  • -mac hmac: Specifies that we want to compute a Message Authentication Code (MAC) using the HMAC method.
  • -macopt hexkey:$HMAC_KEY: This provides the options for the MAC algorithm. Here, we specify that our key is in hexadecimal format (hexkey) and pass the key itself using the environment variable $HMAC_KEY we created earlier.
  • message.txt: The input file containing the data to be authenticated.

Execute the following command to generate the HMAC:

openssl dgst -sha256 -mac hmac -macopt hexkey:$HMAC_KEY message.txt

The output will be the HMAC digest for your message, calculated with your secret key. The output format will show the algorithm used and the resulting HMAC value.

HMAC-SHA2-256(message.txt)= 214fbb56f716dfe1c2f4a60615a5b901b263fd74c9678b2aef4f01779b34dea8

This HMAC value is what you would send along with your message to a recipient who also has the secret key.

Verify HMAC Integrity

In this step, you will see the HMAC verification process in action. You will observe how using the correct key succeeds, while using an incorrect key or a modified message results in failure.

Verification with the Correct Key

Verification isn't a special command; it's simply the act of the receiver re-computing the HMAC on their own and comparing it to the one they received. If you run the command from the previous step again, you will get the exact same HMAC value. This confirms that as long as the key and message are unchanged, the HMAC is consistent.

Observing Failure with a Wrong Key

Now, let's simulate an attacker or an incorrect configuration by trying to verify the message with a different key. First, generate a new, "wrong" key:

export WRONG_KEY=$(openssl rand -hex 32)

Now, try to compute the HMAC for the original message.txt but using this WRONG_KEY:

openssl dgst -sha256 -mac hmac -macopt hexkey:$WRONG_KEY message.txt

You will see a new HMAC value in the output:

HMAC-SHA2-256(message.txt)= 781729497e89f3f9cb1d8c7ab632e22753062ac39cd64de0e5b81a45de245d78

Notice that this HMAC is completely different from the one you generated with the correct $HMAC_KEY. This demonstrates that without the correct secret key, one cannot produce a valid HMAC for the message, thus ensuring authenticity.

Observing Failure with a Modified Message

Let's also see what happens if the message itself is tampered with. We'll modify message.txt slightly:

echo -n "This is a tampered message." > message.txt

Now, compute the HMAC again using the original, correct key ($HMAC_KEY):

openssl dgst -sha256 -mac hmac -macopt hexkey:$HMAC_KEY message.txt

Again, you will get a completely different HMAC value. This proves that any modification to the message, no matter how small, will be detected, thus ensuring integrity.

Implement HMAC in Python

In this step, you will learn how to perform HMAC operations programmatically using Python. This is a common requirement in web applications, APIs, and other software that needs to ensure message security. Python's standard library provides the hmac and hashlib modules for this purpose.

We will write a simple Python script to compute the HMAC-SHA256 of a message. First, open the file hmac_example.py using the nano text editor:

nano hmac_example.py

Now, copy and paste the following Python code into the nano editor. This code imports the necessary libraries, defines a key and a message, and then computes and prints the HMAC.

Note: For this example, we are hardcoding the key and message. In a real application, the key would be securely stored and managed. Both the key and message must be byte strings, so we prepend them with b.

import hmac
import hashlib

## The secret key (must be bytes)
## In a real app, get this from a secure location
key = b'\x0d\xb3\x48\xc7\x84\x73\xce\x84\x60\x41\x6f\x87\x5c\xd8\x72\x39\xd0\xf5\xf6\x6f\xbe\x51\x03\xba\x4b\x5c\x84\xcf\x2c\xd7\x69\x14'

## The message to authenticate (must be bytes)
message = b'This is a secret message.'

## 1. Create a new HMAC object
##    - Pass the key
##    - Pass the message
##    - Specify the hash algorithm (from hashlib)
h = hmac.new(key, message, hashlib.sha256)

## 2. Get the digest in hexadecimal format
hex_digest = h.hexdigest()

print("HMAC Digest:")
print(hex_digest)

After pasting the code, save the file and exit nano by pressing Ctrl+O, then Enter to confirm the filename, and finally Ctrl+X to exit.

Now, run your Python script from the terminal:

python3 hmac_example.py

The script will execute and print the calculated HMAC digest.

HMAC Digest:
214fbb56f716dfe1c2f4a60615a5b901b263fd74c9678b2aef4f01779b34dea8

You have now successfully implemented HMAC generation in Python, a skill that is directly applicable to building secure software.

Summary

In this lab, you have gained practical experience with Hash-based Message Authentication Codes (HMAC), a cornerstone of modern cryptography for ensuring data integrity and authenticity.

You learned that:

  • HMAC combines a cryptographic hash function with a secret key to create a message authentication code.
  • Only parties with the secret key can generate or verify the HMAC, preventing unauthorized modification and forgery.
  • The openssl command-line tool is a powerful utility for performing cryptographic operations, including generating random keys (openssl rand) and computing HMACs (openssl dgst).
  • Any change to the message or the use of an incorrect key will result in a completely different HMAC, making tampering easily detectable.
  • Python provides the hmac and hashlib libraries for easily integrating HMAC functionality into your applications.

By mastering HMAC, you have taken an important step toward building more secure and trustworthy systems.