Message Authentication with HMAC

Understand how HMAC provides message authentication in network protocols. Learn about MAC-then-encrypt, encrypt-then-MAC patterns and their security implications.

API Security

Detailed Explanation

Message Authentication with HMAC

Message authentication is the process of verifying that a message was sent by a legitimate party and has not been modified in transit. HMAC is the most widely used construction for this purpose, providing both data integrity and data origin authentication.

Authentication vs Encryption

A common misconception is that encryption provides authentication. In reality:

  • Encryption hides the content of a message but does not prevent tampering. An attacker can flip bits in ciphertext, and the modified ciphertext will decrypt to a different (possibly meaningful) plaintext.
  • Authentication (via HMAC) proves that the message was created by someone with the secret key and has not been altered, but does not hide the content.
  • Authenticated encryption combines both. Modern protocols (TLS 1.3, AES-GCM) provide both simultaneously.

HMAC in Protocol Design

When designing a protocol that uses separate encryption and authentication, the ordering matters:

Encrypt-then-MAC (recommended):

  1. Encrypt the plaintext: ciphertext = Encrypt(key_e, plaintext)
  2. Compute HMAC over the ciphertext: tag = HMAC(key_m, ciphertext)
  3. Send ciphertext || tag

The receiver first verifies the HMAC, then decrypts only if the tag is valid. This prevents attacks against the decryption process itself.

MAC-then-Encrypt (less secure):

  1. Compute HMAC over the plaintext: tag = HMAC(key_m, plaintext)
  2. Encrypt both: ciphertext = Encrypt(key_e, plaintext || tag)

This is vulnerable to padding oracle attacks (e.g., the BEAST and Lucky13 attacks on TLS CBC cipher suites) because the receiver must decrypt before verifying the MAC.

Using Separate Keys

Always use different keys for encryption and authentication. If you derive both from a single master key, use a proper key derivation function (KDF) like HKDF:

key_encryption = HKDF(master_key, salt, "encryption")
key_authentication = HKDF(master_key, salt, "authentication")

Associated Data

In many protocols, some data is authenticated but not encrypted (e.g., packet headers, version numbers). HMAC can cover both the encrypted payload and the unencrypted associated data, ensuring that an attacker cannot modify headers without invalidating the MAC.

Use Case

HMAC-based message authentication is fundamental to TLS record layer security, IPsec packet authentication, secure messaging protocols, and any networked application where data integrity and origin verification are required alongside or independent of encryption.

Try It — HMAC Generator

Open full tool