简体   繁体   English

PHP双重随机hmac验证,防止时序攻击

[英]PHP 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 https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/february/double-hmac-verification/ ).防止哈希字符串比较的计时攻击的一种方法是执行额外的 HMAC 签名以随机化验证过程(请参阅https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011 /february/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.除了每个散列的第二个 HMAC 散列之外,随机长度的随机盐被添加到两者中,以使散列时间/过程更难以预测。

My 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?有什么可以改进的吗?

A second question is whether it is more advisable to perform the HMAC verification on the plaintext, the ciphertext, or both (as in my example), and why.第二个问题是对明文、密文或两者(如我的示例)执行 HMAC 验证是否更可取,以及为什么。

I've left some comments inline as I read your function.在阅读您的函数时,我已经内联留下了一些评论。 This isn't an analysis after reading the whole thing, rather this is what I immediately think of as I read it.这不是在阅读整篇文章后的分析,而是我在阅读时立即想到的。

function hmac_verify ($hash_original, $message, $key) {
    ##
    # Nitpick: A variable named $hash_original will prime people who read
    # your code to think of simple hash functions rather than HMAC
    ##

    $hmac_salt = '...'; // was added at the original HMAC signing
    ##
    # What is this? $hmac_salt? Looks like a hard coded-salt (a.k.a. pepper).
    # I wouldn't trust this with my life.
    ##

    $random_salt = openssl_random_pseudo_bytes (rand(16,96));
    ##
    # Why are you bothering to randomize this? Just use a static value
    # approximating the output size of the hash function (i.e. 64).
    ##

    $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);
    ##
    # Ah, yeah, don't pepper. HMAC is secure.
    ##
    $hash_original_safe = hash_hmac('sha512', $hash_original, $random_salt, true);

    if ($hash_compare_safe === $hash_original_safe) return true;
        else return false;
    ##
    # Why not just do this?
    # return $hash_compare_safe === $hash_original_safe;
    ## 

}

So, I would highly recommend separating this out into two separate mechanisms: One that calculates MACs and the other that compares strings in constant time (like PHP 5.6's hash_equals() does).因此,我强烈建议将其分为两种不同的机制:一种用于计算 MAC,另一种在恒定时间内比较字符串(如 PHP 5.6 的hash_equals()所做的那样)。

function hmac_verify ($hmac, $message, $key)
{
    $calc = hash_hmac('sha512', $message, $key, true);
    return hmac_equals($hmac, $calc);
}

function hmac_equals($hmac, $calc)
{
    $random = openssl_random_pseudo_bytes(64);
    return (
        hash_hmac('sha512', $hmac, $random)
            ===
        hash_hmac('sha512', $calc, $random)
    );
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM