Double randomised HMAC verification to prevent timing attack A way to prevent timing attacks for hash string comparison is to perform additional HMAC signing in order to randomize the verification process (see Double HMAC Verification). 

In addition to the second HMAC hashing for each hash, a random salt of random length is added to both in order to make the hashing timing / process even less predictable.

My PHP implementation of this look like this:

function hmac_verify ($hash_original, $message, $key) {

    $hmac_salt = '...'; // was added at the original HMAC signing
    $random_salt = openssl_random_pseudo_bytes (rand(16,96));

    $raw_hash = hash_hmac('sha512', $message . $hmac_salt, $key, true);
    $hash_compare = base64_encode ($raw_hash); // $hash_original is in base64 
    $hash_compare_safe = hash_hmac('sha512', $hash_compare, $random_salt, true);
    $hash_original_safe = hash_hmac('sha512', $hash_original, $random_salt, true);

    if ($hash_compare_safe === $hash_original_safe) return true;
        else return false;

}


The function is called in this way after decrypting the encrypted text in order to verify the decryption result:

if (!hmac_verify ($hmac_hash, $plaintext . $cipher_text, $key . $iv)) return "HASH ERROR";


Will this successfully prevent a timing attack? Am I doing anything unnecessary? Could something be improved?
Will this successfully prevent a timing attack?


Strictly speaking you should be checking if openssl_random_pseudo_bytes happens to be returning cryptographically strong numbers or not. If not, an attacker could guess be able to launch a timing attack practically as easily as without the extra HMAC.

(Got to love PHP... Even the function name: random "pseudo bytes"...)

You should also, if possible, HMAC the raw output rather than the base64. The base64 encoding function might itself even allow timing attacks (probably not but who knows), so you would be better off using the raw values. It is also faster.


  Am I doing anything unnecessary? Could something be improved?


The $random_salt is actually a key, so you should call it and treat it as such. You could reuse it across function calls, if you are after performance.

There is no advantage to generating a random-length key. You should be using a key size that matches the overall security strength you are aiming for, but e.g. 256 bits would be plenty.

The security of this relies on the security of HMAC. As long as the key is secret, no one will be able to learn anything about the original hash even if the final comparison leaked the value. And if the key is long enough it cannot be brute forced. Randomness does not help beyond generating a secure key.