在学习密码哈希并保存在数据库中时,我发现了这篇文章:https://crackstation.net/hashing-security.htm#phpsourcecode
一切都很清楚,除了这个功能,我无法理解为什么不使用正常的平等?这意味着:比较两个字符串$ a和$ b的长度 - 恒定时间。
// Compares two strings $a and $b in length-constant time.
function slow_equals($a, $b)
{
$diff = strlen($a) ^ strlen($b);
for($i = 0; $i < strlen($a) && $i < strlen($b); $i++)
{
$diff |= ord($a[$i]) ^ ord($b[$i]);
}
return $diff === 0;
}
答案 0 :(得分:22)
当您通常比较两个字符串是否相等时,如果遇到第一个不等式,算法就会停止。
像这样:&#34; aaa&#34; ==&#34; aba&#34;?第一个角色?两个&#34; a&#34;。第二个字符? &#34;&#34;不是&#34; b&#34;,所以停在这里以节省时间。最后一个角色没有被比较。
当比较安全相关的字符串时,攻击者可能会得到一个线索,哪个字符是正确的,哪个是错误的,因为这样的比较函数的运行时间。
考虑一下使用纯文本密码的不安全做法。如果攻击者可以通过测量密码比较运行的时间长度来判断他猜测的密码的第一个字符是否正确,那么他只需要大约62个猜测(字母字符大小写和数字)来知道第一个字母。使用一个字母,运行时间更长,因为第一个字母与真实密码相同,第二个字母进行了比较。现在第二个字母被迭代了。经过62次猜测后,我们知道了。
这大大削弱了安全性,因为在不知道第一个字母是否正确的情况下,您需要62 * 62猜测两个字母的密码。有了线索,你只需要62 + 62猜测。
长度常数比较函数比较所有字母,并且仅在结尾处显示字符串是否匹配。这样你就无法弄清楚哪个字母已经是正确的了。
哈希字符串混合了一些东西,但是因为你无法知道攻击者是否预先生成了一堆哈希值,或者是在运行中生成它们并且如果哈希值不匹配则不会强制使用相应的密码,你不希望任何人知道那个哈希不匹配的地方。它是一个小小的附加安全组件,但却非常重要。