Generate and verify HMAC message authentication codes using various hash algorithms
HMAC(K, m) = H((K' ⊕ opad) || H((K' ⊕ ipad) || m))
Where: K = Secret key K' = Derived key H = Hash function ⊕ = XOR operation || = Concatenation opad = Outer pad (0x5C...) ipad = Inner pad (0x36...)
HMAC (Hash-based Message Authentication Code) is a specific type of message authentication code (MAC) that uses a cryptographic hash function along with a secret key to verify both the data integrity and authenticity of a message. It provides a way to check that data hasn't been tampered with and to verify that it came from the expected sender.
HMAC operates by combining a cryptographic hash function with a secret key. The process involves:
If the secret key is longer than the hash function's block size, it is first hashed to produce a key of the appropriate length. If it's shorter than the block size, it's padded with zeros.
The derived key is XORed with a constant padding value called the inner pad (ipad, which is the byte 0x36 repeated to fill a block). This value is then concatenated with the message and hashed.
The derived key is XORed with a different constant padding value called the outer pad (opad, which is the byte 0x5C repeated to fill a block). This value is then concatenated with the result of the inner hash and hashed again.
The result of the outer hash becomes the final HMAC value. This two-stage process helps protect against length extension attacks that plain hash functions are vulnerable to.
The formal definition of HMAC is:
HMAC(K, m) = H((K' ⊕ opad) || H((K' ⊕ ipad) || m))
HMAC Algorithm | Output Size | Security Status | Recommended Use |
---|---|---|---|
HMAC-MD5 | 128 bits | Weak (underlying hash is broken) | Legacy systems only |
HMAC-SHA1 | 160 bits | Moderate (underlying hash has weaknesses) | Legacy compatibility |
HMAC-SHA256 | 256 bits | Strong | General purpose security |
HMAC-SHA384 | 384 bits | Very Strong | Enhanced security applications |
HMAC-SHA512 | 512 bits | Very Strong | High-security applications |
Even though some underlying hash algorithms like MD5 and SHA-1 have known cryptographic weaknesses when used alone, HMAC construction provides additional security properties that can mitigate these weaknesses. For example, HMAC-MD5 and HMAC-SHA1 are not as vulnerable to collision attacks as the base hash functions.
However, for new applications, it's recommended to use HMAC with more secure hash functions like SHA-256 or SHA-512.
HMAC is widely used in various security applications and protocols:
Many web APIs use HMAC for request authentication. The client includes an HMAC signature with each request, computed from the request details and a shared secret key. The server independently calculates the same signature and verifies it matches.
Transport Layer Security (TLS) and its predecessor, Secure Sockets Layer (SSL), use HMAC for message authentication during the encrypted communication process.
JWTs often use HMAC algorithms (such as HS256, which is HMAC with SHA-256) to digitally sign the token payload, ensuring it hasn't been tampered with.
HMAC can be used to verify that files haven't been altered, especially in situations where the verification needs to be authenticated (unlike a simple hash check).
While dedicated password hashing functions like bcrypt or Argon2 are preferred, HMAC can be part of a password hashing strategy when combined with appropriate salting and key stretching.
While both HMAC and simple hash functions can verify data integrity, they serve different purposes:
Feature | Simple Hash (e.g., SHA-256) | HMAC (e.g., HMAC-SHA256) |
---|---|---|
Secret Key | No | Yes |
Verifies Data Integrity | Yes | Yes |
Verifies Data Source | No | Yes |
Protection against Length Extension | No (for many hash functions) | Yes |
Use Case | Checksums, data integrity | Authentication, secure messaging |
To ensure the security of your HMAC implementations, follow these best practices:
HMAC is one of several methods for ensuring data integrity and authenticity. Here's how it compares to some alternatives:
Here are examples of computing HMAC-SHA256 in various programming languages:
// Using the Web Crypto API async function calculateHMAC(message, key) { // Convert to byte arrays const encoder = new TextEncoder(); const messageData = encoder.encode(message); const keyData = encoder.encode(key); // Import the key const cryptoKey = await window.crypto.subtle.importKey( 'raw', keyData, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign'] ); // Sign the message const signature = await window.crypto.subtle.sign( 'HMAC', cryptoKey, messageData ); // Convert signature to hex return Array.from(new Uint8Array(signature)) .map(b => b.toString(16).padStart(2, '0')) .join(''); }
function calculateHMAC($message, $key) { return hash_hmac('sha256', $message, $key); } // Example $hmac = calculateHMAC('Hello, world!', 'mysecretkey'); echo $hmac;
import hmac import hashlib def calculate_hmac(message, key): return hmac.new( key.encode('utf-8'), message.encode('utf-8'), hashlib.sha256 ).hexdigest() # Example hmac_value = calculate_hmac('Hello, world!', 'mysecretkey') print(hmac_value)
HMAC is a versatile and widely-used cryptographic primitive that provides authenticated integrity checking for messages. By combining the efficiency of hash functions with the security of a secret key, HMAC offers a robust mechanism for verifying that data hasn't been tampered with and comes from a trusted source.
For most modern applications, HMAC-SHA256 provides an excellent balance of security and performance. However, in contexts where the highest security is required, HMAC-SHA512 offers an even larger security margin. By following best practices in key management and implementation, HMAC can be a cornerstone of your application's security infrastructure.