2013-09-20 2 views
2

У меня есть проблема, чтобы понять два разных способа сравнения строк. Это следующая функция, которая сравнивает две строки. Эта функция используется в компоненте безопасности 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() выполняет правильную работу, поэтому я могу понять преимущество?

А что такое Алгоритм постоянной времени означает? Я думаю, постоянное время не имеет никакого отношения к реальному времени, или если я ошибаюсь?

ответ

5

Эта функция представляет собой обычную функцию сравнения строк. Это не Рабин Карп. Это НЕ постоянное время, это линейное время, независимо от того, что говорится в комментарии. Это также не предотвращает атаки грубой силы.

Как это работает:

  1. если правильные и пользователь при условии, пароли разной длины, сделать $ результата = 0
  2. итерации по пользователю пароля, исключающий каждый из его символы с соответствующим символом правильного пароля (если правильный пароль короче, продолжайте проходить по кругу) и побитовое или каждый результат с результатом $.

Поскольку только побитовое или используется, если какой-либо из символов отличается, $ result будет равен! = 0. Шаг 1 необходим, поскольку в противном случае пользовательский ввод «abca» будет принят, если реальный пароль был « а».

Почему такие функции сравнения строк иногда используются

Давайте предположим, что мы сравниваем струны обычным способом, а правильный пароль «БАК». Предположим также, что я могу точно измерить, сколько времени потребуется для проверки пароля для завершения.

I (пользователь) try a, b, c ... Они не работают.

Затем, я попробую aa. Алгоритм сравнивает первые 2 буквы - b vs a, видит, что это неправильно, и возвращает false.

Сейчас я попробую bb. Алгоритм сравнивает b vs b, они совпадают, поэтому он переходит к букве # 2, сравнивает a против b, видит, что это неправильно, возвращает false. Теперь, поскольку я могу точно выполнить выполнение алгоритма, я знаю, что пароль начинается с «b», потому что второй проход занял больше времени, чем первый - я знаю, что первая буква соответствует.

Поэтому я пробую ba, bb, bc ... Они терпят неудачу.

Теперь я проверяю baa, bbb, см. baa работает медленнее, поэтому вторая буква - a. Таким образом, буква за буквой, я могу определить пароль в числе попыток O (cN) вместо O (c^N), который возьмет грубая сила.

Как правило, это не так важно, поскольку это объяснение может заставить его звучать, потому что маловероятно, что злоумышленник будет время сравнения строк с такой степенью точности. Но иногда это может быть.

Смежные вопросы