【问题标题】:Explanation about constant-time algorithm and string comparision关于常数时间算法和字符串比较的说明
【发布时间】:2013-09-20 11:50:04
【问题描述】:

我很难理解两种不同的字符串比较方式。给出了以下比较两个字符串的函数。 该函数用于 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;
}

来源:origin snippet

我很难理解equals() 函数和简单比较=== 之间的区别。我写了一个简单的工作示例来解释我的问题。

给定字符串:

$password1 = 'Uif4yQZUqmCWRbWFQtdizZ9/qwPDyVHSLiR19gc6oO7QjAK6PlT/rrylpJDkZaEUOSI5c85xNEVA6JnuBrhWJw=='; 
$password2 = 'Uif4yQZUqmCWRbWFQtdizZ9/qwPDyVHSLiR19gc6oO7QjAK6PlT/rrylpJDkZaEUOSI5c85xNEVA6JnuBrhWJw==';
$password3 = 'iV3pT5/JpPhIXKmzTe3EOxSfZSukpYK0UC55aKUQgVaCgPXYN2SQ5FMUK/hxuj6qZoyhihz2p+M2M65Oblg1jg==';

示例 1(按预期操作)

echo $password1 === $password2 ? 'True' : 'False'; // Output: True
echo equals($password1, $password2) ? 'True' : 'False'; // Output: True

示例 2(按预期操作)

echo $password1 === $password3 ? 'True' : 'False'; // Output: False
echo equals($password1, $password3) ? 'True' : 'False'; // Output: False

我读到了Karp Rabin Algorithm,但我不确定equals() 函数是否代表 Karp Rabin Algorithm,总的来说我不理解维基百科的文章。

另一方面,我读到equals() 函数可以防止暴力攻击,对吗?有人可以解释equals() 的优势是什么吗? 或者有人可以给我一个例子,=== 会失败,equals() 做正确的工作,所以我可以理解优势?

恒定时间算法是什么意思?我认为 constant-time 与实时无关,或者如果我错了?

【问题讨论】:

    标签: php algorithm comparison


    【解决方案1】:

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

    工作原理:

    1. 如果正确密码和用户提供的密码长度不同,则设置 $result != 0
    2. 遍历用户提供的密码,将其每个字符与正确密码的相应字符进行异或运算(如果正确密码较短,则继续循环遍历),并使用 $result 按位或每个结果。

    由于只使用按位或,如果任何字符不同,$result 将是 != 0。需要第 1 步,否则,如果真实密码为“abc”,则用户输入“abca”将被接受。

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

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

    我(用户)尝试abc...它们不起作用。

    然后,我尝试aa。该算法比较前 2 个字母 - ba,发现错误,返回 false。

    我现在尝试使用bb。该算法比较 bb,它们匹配,所以它继续到字母 #2,比较 ab,发现它是错误的,返回 false。现在,由于我能够精确计时算法的执行时间,我知道密码以“b”开头,因为第二遍比第一遍花费更多时间 - 我知道第一个字母匹配。

    所以我尝试babbbc...他们失败了。

    现在我检查baabbb,看到baa 运行速度较慢,所以第二个字母是a。这样,我可以逐个字母地在 O(cN) 次尝试中确定密码,而不是使用暴力破解的 O(c^N) 次。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-01
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多