【问题标题】:PHP double randomised hmac verification to prevent timing attackPHP双重随机hmac验证防止定时攻击
【发布时间】:2016-01-24 15:51:37
【问题描述】:

防止哈希字符串比较的计时攻击的一种方法是执行额外的 HMAC 签名以随机化验证过程(请参阅https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/february/double-hmac-verification/)。

除了每个散列的第二个 HMAC 散列之外,还会向两者添加一个随机长度的随机盐,以使散列时间/过程更难以预测。

我的实现如下所示:

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;

}

在解密密文后调用该函数以验证解密结果:

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

这会成功阻止定时攻击吗?我做了什么不必要的事情吗?有什么可以改进的吗?

第二个问题是对明文、密文或两者(如我的示例)执行 HMAC 验证是否更可取,以及为什么。

【问题讨论】:

  • 这个问题更适合Code Review,因为这段代码大概可以工作(没有问题需要解决)并且CodeReview特别欢迎关于安全问题的问题。
  • 考虑到安全性,您最好使用Cryptography,引用他们的帮助中心的话:“但是,您可能希望将问题分解为具体问题,例如“在这些条件下,结构 X 是否具有所需的安全属性 Y?”这对我们来说是完美的选择。”
  • @Vogel612 问题是Cryptography 通常不处理有代码的问题,所以这可能是题外话。这也是为什么Information Security 也可能不适合问这个问题的原因。
  • @ArtjomB。嗯...我在Information Security (exhibit a) 上看到了与代码相关的问题,根据帮助中心的说法,加密似乎没问题。然后我又没有积极参与那里......
  • 谢谢大家,我把它贴在这里了:crypto.stackexchange.com/questions/30084/…

标签: php security hash hmac timing-attack


【解决方案1】:

我在阅读您的函数时留下了一些内联的 cmets。这不是阅读全文后的分析,而是我阅读后立即想到的。

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;
    ## 

}

因此,我强烈建议将其分成两种独立的机制:一种用于计算 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)
    );
}

【讨论】:

  • 谢谢,这真的很有帮助。你不认为辣椒对 HMAC 散列有用吗?
  • blog.ircmaxell.com/2015/03/… - Peppering 通常被认为是无用的。
猜你喜欢
  • 2015-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-11
  • 1970-01-01
  • 2014-11-30
  • 2021-12-08
  • 1970-01-01
相关资源
最近更新 更多