首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >关于常数时间算法和字符串比较的解释

关于常数时间算法和字符串比较的解释
EN

Stack Overflow用户
提问于 2013-09-20 11:50:04
回答 1查看 703关注 0票数 2

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

代码语言:javascript
复制
/**
 * 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;
}

产地:起源片段

我有问题要理解equals()函数和简单比较===之间的区别。我写了一个简单的例子来解释我的问题。

给定字符串:

代码语言:javascript
复制
$password1 = 'Uif4yQZUqmCWRbWFQtdizZ9/qwPDyVHSLiR19gc6oO7QjAK6PlT/rrylpJDkZaEUOSI5c85xNEVA6JnuBrhWJw=='; 
$password2 = 'Uif4yQZUqmCWRbWFQtdizZ9/qwPDyVHSLiR19gc6oO7QjAK6PlT/rrylpJDkZaEUOSI5c85xNEVA6JnuBrhWJw==';
$password3 = 'iV3pT5/JpPhIXKmzTe3EOxSfZSukpYK0UC55aKUQgVaCgPXYN2SQ5FMUK/hxuj6qZoyhihz2p+M2M65Oblg1jg==';

示例1(按预期行事)

代码语言:javascript
复制
echo $password1 === $password2 ? 'True' : 'False'; // Output: True
echo equals($password1, $password2) ? 'True' : 'False'; // Output: True

示例2(按预期行事)

代码语言:javascript
复制
echo $password1 === $password3 ? 'True' : 'False'; // Output: False
echo equals($password1, $password3) ? 'True' : 'False'; // Output: False

我读过关于Karp算法的文章,但我不确定equals()函数是否代表Karp算法,而且总的来说,我不理解维基百科的文章。

另一方面,我读到equals()函数将防止暴力攻击,对吗?有人能解释一下equals()的优势是什么吗?或者有人能给我举个例子,说明===会失败,equals()会做正确的工作,这样我就能理解它的优势了吗?

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-09-20 12:31:02

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

的工作方式:

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

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

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

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

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

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

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

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

现在我检查baabbb,看到baa运行得慢,所以第二个字母是a。通过这种方式,我可以在一个O(cN)的尝试次数中确定密码,而不是用蛮力的O(c^N)来确定密码。

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

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18916072

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档