How to Use PHP hash_hmac for Authentication

This article explains how the hash_hmac() function provides cryptographic message authentication in PHP. You will learn the mechanics behind Keyed-Hash Message Authentication Codes (HMAC), the syntax of the PHP function, why it is superior to simple hashing for security, and how to implement and verify HMACs securely in your applications.

What is hash_hmac()?

The hash_hmac() function in PHP is used to generate a Keyed-Hash Message Authentication Code (HMAC). An HMAC is a specific type of message authentication code that involves a cryptographic hash function in combination with a secret cryptographic key.

By combining the message data with a secret key, hash_hmac() ensures both data integrity (proving the message has not been altered) and authenticity (proving the message was sent by someone who possesses the secret key).

How hash_hmac() Works

When you hash a message using a standard hashing function like sha256, anyone can intercept the message, alter it, and recalculate the hash.

The hash_hmac() function prevents this by incorporating a shared secret key into the hashing process. The calculation is done in two passes: 1. The secret key is mixed with the message, and the result is hashed. 2. The inner hash is mixed with the key again and hashed a second time.

This two-step process makes it computationally impossible for an attacker to alter the message and generate a valid hash without knowing the secret key, even if they know the hashing algorithm used. It also protects against length extension attacks, which standard hashing algorithms like SHA-256 are vulnerable to when used naively for authentication.

Syntax and Parameters

The syntax for the function is:

hash_hmac(string $algo, string $data, string $key, bool $binary = false): string

Practical Code Example

Below is a simple implementation of generating an HMAC signature for an API request payload.

// The payload to be sent
$message = "action=transfer&amount=100&recipient=user123";

// A strong, shared secret key
$secretKey = "super-secure-shared-secret-key";

// Generate the HMAC signature using SHA-256
$signature = hash_hmac('sha256', $message, $secretKey);

echo "Payload: " . $message . "\n";
echo "Signature: " . $signature;

Verifying the HMAC Safely

To verify the message on the receiving end, the receiver recalculates the HMAC using the same secret key and the received message, then compares it to the sent signature.

To prevent timing attacks (where an attacker can guess the signature character-by-character based on how long the comparison takes), you must use PHP’s hash_equals() function for the comparison instead of the standard == or === operators.

// Received payload and signature
$receivedMessage = "action=transfer&amount=100&recipient=user123";
$receivedSignature = "the-signature-sent-by-sender";

// Recalculate the expected signature
$expectedSignature = hash_hmac('sha256', $receivedMessage, $secretKey);

// Securely compare the signatures
if (hash_equals($expectedSignature, $receivedSignature)) {
    echo "Message is authentic and untampered.";
} else {
    echo "Authentication failed. Invalid signature.";
}

By utilizing hash_hmac() paired with hash_equals(), PHP developers can easily implement secure, tamper-proof message transport systems, API authentication, and secure token verification.