Подтвердить что ты не робот

Безопасная функция сравнения строк

Я просто встретил этот код в библиотеке HTTP Auth Zend Framework. Кажется, что используется специальная функция сравнения строк, чтобы сделать ее более безопасной. Однако я не совсем понимаю комментарии. Может ли кто-нибудь объяснить, почему эта функция более безопасна, чем делать $a == $b?

/**
 * Securely compare two strings for equality while avoided C level memcmp()
 * optimisations capable of leaking timing information useful to an attacker
 * attempting to iteratively guess the unknown string (e.g. password) being
 * compared against.
 *
 * @param string $a
 * @param string $b
 * @return bool
 */
protected function _secureStringCompare($a, $b)
{
    if (strlen($a) !== strlen($b)) {
        return false;
    }
    $result = 0;
    for ($i = 0; $i < strlen($a); $i++) {
        $result |= ord($a[$i]) ^ ord($b[$i]);
    }
    return $result == 0;
}
4b9b3361

Ответ 1

Похоже, они пытаются предотвратить синхронизирующие атаки.

В криптографии временная атака представляет собой атаку с боковым каналом, в которой злоумышленник пытается скомпрометировать криптосистему, анализируя время, затраченное на выполнение криптографических алгоритмов. Каждая логическая операция в компьютере требует времени для выполнения, и время может отличаться в зависимости от ввода; с точными измерениями времени для каждой операции, злоумышленник может работать обратно на вход.

В принципе, если для сравнения правильного пароля и неправильного пароля требуется другое количество времени, вы можете использовать время, чтобы выяснить, сколько символов пароля вы правильно догадались.

Рассмотрим крайне ошибочное сравнение строк (это в основном нормальная функция равенства строк, с очевидным добавлением wait):

function compare(a, b) {
    if(len(a) !== len(b)) { 
        return false;
    }
    for(i = 0; i < len(a); ++i) {
        if(a[i] !== b[i]) {
            return false;
        }
        wait(10); // wait 10 ms
    }
    return true;
}

Скажем, вы даете пароль, и он (последовательно) занимает некоторое время для одного пароля и более 10 мс для другого. Что это говорит вам? Это означает, что второй пароль имеет еще один символ, отличный от первого.

Это позволяет вам взломать фильм - где вы угадываете пароль по одному символу за раз (что намного проще, чем угадывать каждый возможный пароль).

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

Эта функция по-прежнему имеет незначительную проблему:

if(strlen($a) !== strlen($b)) { 
    return false;
}

Он позволяет вам использовать временные атак, чтобы выяснить правильную длину пароля, что позволяет вам не утруждать себя угадыванием более коротких или более длинных паролей. В общем, вы хотите сначала перенести свои пароли (который будет создавать строки с равной длиной), поэтому я предполагаю, что они не считают, что это проблема.