4
$\begingroup$

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?

$\endgroup$
0

1 Answer 1

5
$\begingroup$

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.

$\endgroup$
13
  • $\begingroup$ Thanks. Openssl_random_pseudo_bytes is cryptographically strong (see e.g. security.stackexchange.com/questions/26206/…). Can you explain why using a key of random length has no advantage over a fixed-length key, since it adds to the randomness of the string comparison? $\endgroup$
    – azren
    Oct 25, 2015 at 22:04
  • $\begingroup$ @azenz, behind that link they use the same "strictly speaking" wording (by chance, I hadn't seen that before). I added some justification for why random length key won't help. $\endgroup$
    – otus
    Oct 26, 2015 at 5:18
  • $\begingroup$ "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." I disagree; it should be treated a nonce so as to guarantee that the timing side-channel is blinded. $\endgroup$ Oct 26, 2015 at 8:04
  • $\begingroup$ @ScottArciszewski, nonces are not secret. If you assume the adversary knows $random_salt they can brute force the HMAC just as if there was no blinding. On the other hand, reuse of the value does not lead to any attacks (that I can tell – correct me if I'm wrong of course). $\endgroup$
    – otus
    Oct 26, 2015 at 8:49
  • 1
    $\begingroup$ @ScottArciszewski the comments aren't really the place to discuss this. Maybe one of us should ask a new question about this? $\endgroup$
    – otus
    Oct 26, 2015 at 9:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.