Compare trusted authentication values with PHP’s timing-safe hash_equals rather than regular string equality.
The examples introduce the underlying control before showing a verification and an application-level safeguard.
What You Will Build
Compare trusted authentication values with PHP’s timing-safe hash_equals rather than regular string equality.
Prerequisites
Use PHP 8.4 or newer, HTTPS for all authentication operations, and an application session or database where required. Example configuration values are placeholders, never production secrets.
Example 1: Basic Operation
Compare fixed-length HMAC values using hash_equals.
<?php
$secret = 'local-demo-key';
$known = hash_hmac('sha256', 'message', $secret);
$provided = hash_hmac('sha256', 'message', $secret);
var_dump(hash_equals($known, $provided));
Example 2: A Different Use Case
Check a failure without normal string equality.
<?php
$expected = hash('sha256', 'token-a');
$received = hash('sha256', 'token-b');
var_dump(hash_equals($expected, $received));
Practical Example: Checking the Result
Validate expected fixed-length encoding before a timing-safe comparison.
<?php
$received = $_SERVER['HTTP_X_SIGNATURE'] ?? '';
$expected = hash_hmac('sha256', 'fixed-test-payload', 'test-key');
if (!is_string($received) || !preg_match('/^[a-f0-9]{64}$/D', $received) || !hash_equals($expected, $received)) {
http_response_code(401);
exit;
}
Important Behavior and Edge Cases
Keep the known secret first; lengths may still be inferred, so compare fixed-length MACs or hashes when possible.
Enforce controls on the server, test denial paths and do not assume that a snippet alone implements an entire production workflow.
Comparison with Related Functions
| Approach | Key distinction |
|---|---|
| Preventing Timing Attacks with hash_equals() | Compare trusted authentication values with PHP’s timing-safe hash_equals rather than regular string equality. |
| Related technique | hash_equals verifies equality only; the message MAC still needs to be computed securely. |
Common Beginner Mistakes
| Mistake | Correct approach |
|---|---|
| Confusing this operation with a neighboring cryptographic or security mechanism | hash_equals verifies equality only; the message MAC still needs to be computed securely. |
| Ignoring a security prerequisite or failure case | Keep the known secret first; lengths may still be inferred, so compare fixed-length MACs or hashes when possible. |
Key Takeaways
- Compare trusted authentication values with PHP’s timing-safe hash_equals rather than regular string equality.
- Keep the known secret first; lengths may still be inferred, so compare fixed-length MACs or hashes when possible.
- hash_equals verifies equality only; the message MAC still needs to be computed securely.
Apply this behavior to a real application only after confirming the required extension, configuration and failure handling on the deployment runtime.