[英]PHP double randomised hmac verification to prevent timing attack
防止哈希字符串比较的计时攻击的一种方法是执行额外的 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 验证是否更可取,以及为什么。
在阅读您的函数时,我已经内联留下了一些评论。 这不是在阅读整篇文章后的分析,而是我在阅读时立即想到的。
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)
);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.