Table of contents
- What is HMAC
- How HMAC works
- Why use a hash function
- HMAC vs traditional MACs
- What are GAS functions (Generalized Authentication Services)
- Where HMAC is used
- Advantages of HMAC
- Disadvantages and limitations
- Comparison: HMAC vs other authentication methods
Verifying that messages are authentic and unaltered is critical. One of the most reliable tools for this is the HMAC, short for Hash-based Message Authentication Code.
This mechanism allows two parties to ensure that a message hasn’t been tampered with and comes from a trusted source, using hash functions in combination with a shared secret key.
In this article, we’ll explore what HMAC is, how it works in detail, the role of cryptographic hash functions, its advantages compared to other authentication methods, and why it’s widely used in APIs, VPNs, and HTTPS communications.
What is HMAC
Detailed Definition
HMAC, or Hash-based Message Authentication Code, is a type of MAC (Message Authentication Code) that uses a cryptographic hash function along with a shared secret key to verify message integrity and authentication.
Essentially, HMAC produces a unique signature for a message that can be verified only by someone who knows the shared key. Any modification to the message or the key will result in a completely different HMAC.
How HMAC works
HMAC is built using two applications of a hash function, such as SHA-256. It works by hashing the key and message in a specific way using inner and outer paddings and the XOR operation.
Official formula:
HMAC(K, m) = H((K' ⊕ opad) || H((K' ⊕ ipad) || m))
Where:
- K is the secret key
- m is the message
- K’ is the key padded to the hash block size
- ⊕ is XOR
- opad and ipad are fixed padding values
- || is concatenation
- H is the hash function (e.g., SHA-256)
Practical Python example
import hmac
import hashlib
# Shared secret key
key = b'secret123'
# Message to authenticate
message = b'HMAC message authentication'
# HMAC with SHA-256
mac = hmac.new(key, message, hashlib.sha256)
print("HMAC:", mac.hexdigest())
Sample Output:
HMAC: 3c7dd2b2b7060f12be2c8faeeb9cf78ebd2f0ea746c643f3aa7cbf0f5b8072c9
This value changes if:
- The message is altered
- A different key is used
- The hash algorithm is changed
Verifying HMAC
# Message and HMAC received
received_message = b'HMAC message authentication'
received_hmac = b'3c7dd2b2b7060f12be2c8faeeb9cf78ebd2f0ea746c643f3aa7cbf0f5b8072c9'
# Recalculate the HMAC
mac_check = hmac.new(key, received_message, hashlib.sha256)
# Compare securely
if hmac.compare_digest(mac_check.hexdigest(), received_hmac.decode()):
print("Message is authentic and unchanged.")
else:
print("Warning: the message may have been tampered with.")
Why HMAC matters
HMAC is critical because it:
- Protects data in transit
- Authenticates the sender
- Prevents tampering with messages
It is used in:
- HTTPS and SSL/TLS
- JWT tokens
- API authentication
- VPN security
- Firmware and OTA updates
How HMAC works
Logical structure of operation
The HMAC (Hash-based Message Authentication Code) mechanism uses a cryptographic hash function (e.g., SHA-256) in combination with a secret key and a message. It produces a unique authentication code that ensures:
- The message hasn’t been altered
- The message came from someone who knows the shared secret
The mechanism involves two hash operations:
- An inner hash using the message and a key-derived padding (ipad)
- An outer hash using the result of the first hash and another key-derived padding (opad)
Steps of HMAC calculation
1. Key normalization
The key K is adjusted:
- If too long, it is hashed
- If too short, it is padded with zeros until it reaches the block size of the hash function (e.g. 64 bytes for SHA-256)
block_size = 64
if len(key) > block_size:
key = hashlib.sha256(key).digest()
elif len(key) < block_size:
key = key + b'\x00' * (block_size - len(key))
2. Create padding
- ipad = 0x36 * block_size
- opad = 0x5c * block_size
3. XOR operations
- K_ipad = K ⊕ ipad
- K_opad = K ⊕ opad
4. Hashing
- Inner hash: H(K_ipad || message)
- Outer hash: H(K_opad || inner_hash)
Custom HMAC in Python (manual version)
import hashlib
def hmac_sha256(key, message):
block_size = 64
if len(key) > block_size:
key = hashlib.sha256(key).digest()
if len(key) < block_size:
key += b'\x00' * (block_size - len(key))
o_key_pad = bytes([b ^ 0x5c for b in key])
i_key_pad = bytes([b ^ 0x36 for b in key])
inner = hashlib.sha256(i_key_pad + message).digest()
return hashlib.sha256(o_key_pad + inner).hexdigest()
# Example usage
key = b'secret123'
msg = b'HMAC authentication'
print("HMAC:", hmac_sha256(key, msg))
Why two hashes?
The dual-hashing design:
- Prevents message/key collisions
- Guards against length extension attacks
- Makes HMAC secure even if the hash has minor flaws
Diagram of process
K ---⊕--- ipad ----->| |
| Inner Hash |----⊕--- opad --> Outer Hash --> HMAC
message ------------>| |
This shows how the key is used twice, but always mixed with paddings before hashing.
Receiver’s role
The recipient:
- Receives message + HMAC
- Recomputes HMAC using the same secret key
- Compares the result using compare_digest() to avoid timing attacks
Summary: What does HMAC guarantee?
- Integrity
Any change alters the HMAC - Authentication
Only someone with the key can compute it - Efficiency
Lightweight and suitable even for IoT devices
Why use a hash function
Hash functions such as SHA-256, SHA-3, and BLAKE2 are essential to HMAC for several reasons:
- Determinism
The same input always produces the same output - Avalanche effect
A small change in input produces a drastically different output - Speed
Hashes are fast to compute - Collision resistance
Hard to find two inputs that yield the same hash
These properties make hash functions perfect for verifying data integrity. HMAC adds authentication by combining the hash with a secret key.
HMAC vs traditional MACs
What are MACs
A MAC (Message Authentication Code) is a cryptographic value used to ensure the authenticity and integrity of a message. MACs are usually symmetric, meaning both sender and receiver share the same secret key.
Different types of MACs include:
- CBC-MAC
Based on a block cipher (e.g., AES) - CMAC
An improved version of CBC-MAC - HMAC
Based on a hash function
Technical comparison: HMAC vs traditional MACs
Feature | HMAC | Traditional MACs (e.g., CBC-MAC) |
Underlying algorithm | Hash function (e.g., SHA-256) | Block cipher (e.g., AES) |
Key type | Symmetric | Symmetric |
Performance | High on general-purpose hardware | High on encryption-optimized hardware |
Security | Very high, even on variable input | High only on fixed-length input |
Known weaknesses | Very few, well understood | CBC-MAC insecure for variable-length messages |
Ease of implementation | High | More complex |
Standard | RFC 2104 | NIST SP 800-38B (for CMAC) |
Portability | Excellent | Depends on cipher availability |
Typical use cases | APIs, JWT, TLS, IoT | Firmware auth, embedded protocols |
Practical example: HMAC vs CBC-MAC in Python
HMAC:
python
CopiaModifica
import hmac
import hashlib
key = b'secret123'
msg = b'Important message'
mac = hmac.new(key, msg, hashlib.sha256)
print("HMAC:", mac.hexdigest())
Simulated CBC-MAC (simplified):
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
key = b'16bytekey1234567'
msg = b'Important message'
cipher = AES.new(key, AES.MODE_CBC, iv=b'\x00'*16)
mac_result = cipher.encrypt(pad(msg, 16))[-16:]
print("CBC-MAC:", mac_result.hex())
Note: CBC-MAC is not safe for variable-length input unless extended (e.g., CMAC).
Security with variable input
- CBC-MAC fails on messages of different lengths unless adjusted
- HMAC remains secure regardless of message length
Protocol integration
- HMAC: TLS/SSL, IPsec, OAuth, JWT, Amazon S3, VPNs
- CBC-MAC / CMAC: Firmware verification, NFC, embedded AES systems
Which one to choose
Scenario | Recommended MAC |
Web apps, APIs, cloud-based systems | HMAC |
Hardware-accelerated embedded systems (AES) | CMAC or CBC-MAC with care |
Variable-length messages | HMAC |
Legacy systems | CBC-MAC (cautiously) |
Cross-platform support | HMAC |

What are GAS functions (Generalized Authentication Services)
GAS (Generalized Authentication Services) isn’t a specific algorithm but a framework or group of services that include mechanisms like HMACs, digital signatures, and certificates to authenticate entities in distributed systems.
For example, in security frameworks like Kerberos or zero-trust architectures, generalized authentication services handle:
- Identity verification
- Secure key exchanges
- HMAC-based token generation and validation
In this context, HMAC is a building block within GAS that helps protect communications, generate signed tokens, and validate secure access requests in OAuth, OpenID, and SAML systems.
Where HMAC is used
HMAC is used across many real-world applications, such as:
- REST APIs
To authenticate client-server requests - JWT (JSON Web Tokens)
To sign tokens - TLS/SSL
To ensure message integrity - IPsec and SSL VPNs
To authenticate packets - Firmware and OTA updates
To validate that updates weren’t tampered with - Embedded IoT systems
For mutual authentication between devices
Advantages of HMAC
Some of the key benefits of HMAC include:
- High security
Combines hash properties with key-based authentication - High performance
Efficient and fast on most hardware - Flexibility
Compatible with any secure hash function - Standardized
Defined in RFC 2104 and widely supported
Disadvantages and limitations
Despite its strengths, HMAC also has some limitations:
- If the secret key is compromised, all security is lost
- Requires secure key exchange since it’s symmetric
- Lacks non-repudiation, unlike digital signatures
Comparison: HMAC vs other authentication methods
Method | Key Type | Pros | Cons |
HMAC | Symmetric | Fast, simple, secure | Requires secure key exchange |
RSA/ECC Signatures | Asymmetric | Non-repudiation | Slower, more complex |
CBC-MAC | Symmetric | Efficient for fixed lengths | Not safe for variable-length data |
JWT-HMAC | Symmetric | Lightweight, flexible | Not legally binding |
Questions and answers
- What is HMAC?
A message authentication code that uses a hash function and a secret key. - What is HMAC used for?
To ensure that a message hasn’t been tampered with and comes from a legitimate sender. - What hash functions are used in HMAC?
Common choices include SHA-256, SHA-1, SHA-3, and BLAKE2. - Is HMAC secure?
Yes, when used with a secure hash function and a sufficiently long secret key. - Is HMAC the same as a digital signature?
No, HMAC uses symmetric keys and does not provide non-repudiation. - Where is HMAC commonly used?
In TLS, VPNs, REST APIs, JWTs, firmware updates, and IoT devices. - How is HMAC different from hashing?
Hashing is public and one-way; HMAC adds a secret key for authentication. - What is a GAS function?
A generalized framework for authenticating users and systems, often using HMACs. - Can HMAC be decrypted?
No, but anyone with the key can recompute and verify it. - Are there alternatives to HMAC?
Yes, including CMAC, CBC-MAC, and public-key digital signatures.