Message Authentication Codes (MAC)

A Message Authentication Code (MAC) provides integrity (the message hasn’t been tampered with) and authenticity (the message is from the expected source). A MAC is generated by combining the message m with a secret key k through a deterministic algorithm to produce a tag T.

HMAC (Hash-based MAC)

HMAC uses a cryptographic hash function (e.g., SHA-256) in combination with a secret key. It applies the hash function twice with two distinct padding keys derived from the original key (ipad and opad).

Steps for HMAC computation:

  1. Pad the key to match the block size of the hash function.
  2. Compute inner_hash = hash(key XOR ipad || message).
  3. Compute T = hash(key XOR opad || inner_hash).

Example in Python:

import hmac
import hashlib
 
key = b'secret_key'
message = b'important_data'
hmac_tag = hmac.new(key, message, hashlib.sha256).hexdigest()
print("HMAC Tag:", hmac_tag)

CMAC (Cipher-based MAC)

CMAC uses a block cipher (like AES) instead of a hash function. It processes the message in blocks, applying the cipher in a chaining mode similar to CBC (Cipher Block Chaining).

Steps for CMAC:

  1. Divide the message into blocks and pad the last block if needed.
  2. Encrypt each block using the AES key, combining them sequentially.
  3. The final output is the MAC tag.

Example (pseudocode):

CMAC(K, M):
    Divide M into blocks M1, M2, ..., Mn
    MAC = 0
    For each block:
        MAC = AES-Encrypt(K, MAC XOR Mi)
    Return MAC

Key Derivation Functions (KDFs)

Key Derivation Functions are used to derive one or more cryptographic keys from a shared secret, such as a password or master key. KDFs ensure that the derived keys are strong, even if the input secret has weaknesses.

Examples of KDFs

  • PBKDF2: A simple KDF that iteratively hashes the input with a salt and repeats the process thousands of times to slow down brute force attacks.
from hashlib import pbkdf2_hmac
 
password = b'password123'
salt = b'unique_salt'
derived_key = pbkdf2_hmac('sha256', password, salt, 100000)
print("Derived Key:", derived_key.hex())
  • HKDF: Extends HMAC for key derivation, using a two-step process: extracting entropy from the input and expanding it into usable keys.

Block Ciphers and Modes of Operation

A block cipher encrypts fixed-size blocks of data using a secret key. To handle arbitrary-length inputs, block ciphers use modes of operation. Common modes are:

  1. ECB (Electronic Codebook): Each block is encrypted independently. It’s insecure because identical plaintext blocks produce identical ciphertext blocks, revealing patterns.
Plaintext:  AAAA BBBB AAAA
Ciphertext: C1    C2    C1
  1. CBC (Cipher Block Chaining): Encrypts each block by XORing it with the previous ciphertext block. Requires an initialization vector (IV).
C1 = Encrypt(P1 XOR IV)
C2 = Encrypt(P2 XOR C1)
  1. CTR (Counter Mode): Turns a block cipher into a stream cipher by combining the plaintext with a counter value(1,2,3) combined with a nonce and encrypted using the block cipher. Highly parallelizable.
C1 = P1 XOR Encrypt(CTR1 || nonce)
C2 = P2 XOR Encrypt(CTR2 || nonce)
  1. GCM (Galois/Counter Mode): Provides both encryption and integrity/authentication in one step. Used in modern protocols like TLS.

Tip

The type of cipher and the block mode is combined, for example **AES-GCM

CTR is highly parallelizable

It doesn’t need the result of the previous operation like CBC, but you need to share the nonce and the initial counter with the other party

Galois/Counter Mode (GCM)

GCM is an extension of CTR mode that includes authentication. It not only encrypts data but also ensures integrity using a mechanism called the Galois field multiplication. Here’s how it works:

  1. Encryption: It uses CTR mode to encrypt plaintext into ciphertext.
  2. Authentication: It computes an authentication tag using the ciphertext, a nonce, and optional additional authenticated data (AAD). The tag ensures that:
    • The ciphertext hasn’t been tampered with.
    • Any associated data (like headers) is also verified for integrity.
  3. Decryption: The ciphertext is decrypted with CTR mode, and the authentication tag is verified before accepting the plaintext.

The authentication step uses a hash function based on Galois field multiplication for fast and secure integrity checks.

Authenticated Encryption

Authenticated Encryption (AE) combines encryption and integrity protection into a single process, preventing attacks like tampering or replay. It’s implemented through integrated algorithms like AES-GCM or ChaCha20-Poly1305, or by combining encryption with a MAC (e.g., Encrypt-then-MAC).

Example with AES-GCM:

from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
 
key = AESGCM.generate_key(bit_length=128)
aesgcm = AESGCM(key)
nonce = os.urandom(12)
plaintext = b"secure data"
associated_data = b"auth header"
ciphertext = aesgcm.encrypt(nonce, plaintext, associated_data)
print("Ciphertext:", ciphertext)

Plaintext message in MAC

Authenticated encryption such as encrypt-then-MAC or integrated ciphers such as AES-GCM prevent the original message to travel in plaintext, protecting confidentiality

ETM or EMT?

Encrypt-then-MAC is preferred to MAC-then-encrypt because on the decoding side, the first step is going to be to validate the MAC. If such validation fails because the message has been tampered, the decryption won’t even be tried and it cannot possibly expose weaknesses.

Practical Applications

HMAC in TLS

HMAC ensures the integrity of messages exchanged between client and server in Transport Layer Security (TLS). Before 1.2, HMAC then Encrypt was the preferred approach, but this doesn’t protect the MAC from tampering because encryption only guarantees confidentiality and not integrity. Vulnerabilities such as padding oracle attacks exploit this vulnerability

Since 1.2, Encrypt-then-HMAC becomes the standard, from 2013, through RFC 3766. In TLS 1.3, Authenticated Encryption with Associated Data (AEAD) ciphers replace the explicit usage of HMAC for record integrity, since AEAD implicitly implement encrypts-then-MAC

CMAC in IoT

In resource-constrained devices like IoT sensors, CMAC is often used because it relies on existing AES implementations, reducing overhead.

Block Cipher Modes in VPNs

AES-CBC or AES-GCM is commonly used in VPN protocols to encrypt traffic securely.