Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 关于常数时间算法和字符串比较的说明_Php_Algorithm_Comparison - Fatal编程技术网

Php 关于常数时间算法和字符串比较的说明

Php 关于常数时间算法和字符串比较的说明,php,algorithm,comparison,Php,Algorithm,Comparison,我很难理解两种不同的字符串比较方法。下面给出了比较两个字符串的函数。 此函数在Symfony Framework安全组件中用于比较用户登录过程中的密码 /** * Compares two strings. * * This method implements a constant-time algorithm to compare strings. * * @param string $knownString The string of known length to compare

我很难理解两种不同的字符串比较方法。下面给出了比较两个字符串的函数。 此函数在Symfony Framework安全组件中用于比较用户登录过程中的密码

/**
 * Compares two strings.
 *
 * This method implements a constant-time algorithm to compare strings.
 *
 * @param string $knownString The string of known length to compare against
 * @param string $userInput   The string that the user can control
 *
 * @return Boolean true if the two strings are the same, false otherwise
 */
function equals($knownString, $userInput)
{
    // Prevent issues if string length is 0
    $knownString .= chr(0);
    $userInput .= chr(0);

    $knownLen = strlen($knownString);
    $userLen = strlen($userInput);

    $result = $knownLen - $userLen;

    // Note that we ALWAYS iterate over the user-supplied length
    // This is to prevent leaking length information
    for ($i = 0; $i < $userLen; $i++) {
        // Using % here is a trick to prevent notices
        // It's safe, since if the lengths are different
        // $result is already non-0
        $result |= (ord($knownString[$i % $knownLen]) ^ ord($userInput[$i]));
    }

    // They are only identical strings if $result is exactly 0...
    return 0 === $result;
}
例1按预期行事

例2按预期行事

我读过关于的,但我不确定equals函数是否表示 一般来说,我不理解维基百科的文章

另一方面,我读到equals函数可以防止暴力攻击,对吗?有人能解释一下平等的好处是什么吗? 或者有人能给我举个例子,其中===将失败,而equals做正确的工作,这样我就可以理解它的优点了


常数时间算法意味着什么?我认为常数时间和实时无关,或者我错了吗?

这个函数只是一个普通的字符串比较函数。这不是拉宾·卡普。它不是常数时间,它是线性时间,不管评论怎么说。它也不能防止暴力攻击

工作原理:

如果正确密码和用户提供的密码长度不同,则生成$result!=0 迭代用户提供的密码,如果正确的密码较短,则将其每个字符与正确密码的对应字符进行异或运算,在循环中继续遍历,并使用$result按位或每个结果。 由于只使用按位or,如果任何字符不同,$result将为!=0第1步是必需的,因为否则,如果真实密码是abc,则会接受用户输入abca

为什么有时会使用这样的字符串比较函数

假设我们以通常的方式比较字符串,正确的密码是bac。我们还假设我可以精确地测量密码检查完成所需的时间

我希望用户尝试a、b、c。。。它们不起作用

然后,我试试aa。该算法比较前两个字母-b和a,发现错误,并返回false

我现在试试bb。算法将b与b进行比较,它们匹配,因此它继续使用字母2,将a与b进行比较,发现错误,返回false。现在,由于我能够精确地计算算法的执行时间,我知道密码以b开头,因为第二次传递比第一次花费更多的时间-我知道第一个字母匹配

所以我尝试了ba,bb,bc。。。他们失败了

现在我检查baa,bbb,看到baa运行较慢,所以第二个字母是a。通过这种方式,一个字母一个字母地,我可以确定OcN尝试次数中的密码,而不是暴力使用的Oc^N

这通常不像这个解释听起来那么令人担忧,因为攻击者不太可能将字符串比较的时间精确到这样的程度。但有时可能是这样

$password1 = 'Uif4yQZUqmCWRbWFQtdizZ9/qwPDyVHSLiR19gc6oO7QjAK6PlT/rrylpJDkZaEUOSI5c85xNEVA6JnuBrhWJw=='; 
$password2 = 'Uif4yQZUqmCWRbWFQtdizZ9/qwPDyVHSLiR19gc6oO7QjAK6PlT/rrylpJDkZaEUOSI5c85xNEVA6JnuBrhWJw==';
$password3 = 'iV3pT5/JpPhIXKmzTe3EOxSfZSukpYK0UC55aKUQgVaCgPXYN2SQ5FMUK/hxuj6qZoyhihz2p+M2M65Oblg1jg==';
echo $password1 === $password2 ? 'True' : 'False'; // Output: True
echo equals($password1, $password2) ? 'True' : 'False'; // Output: True
echo $password1 === $password3 ? 'True' : 'False'; // Output: False
echo equals($password1, $password3) ? 'True' : 'False'; // Output: False