Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Чому секретні рядки порівнюють через hash_equals, а не через ===?

=== порівнює рядки посимвольно і зупиняється на першій розбіжності. Отже, час порівняння залежить від того, скільки перших символів збіглося. Вимірюючи час відповіді на багатьох запитах, нападник може підбирати секрет символ за символом - це timing-атака.

hash_equals() порівнює рядки за сталий час: завжди проходить усю довжину, незалежно від того, де розбіжність.

// Перевірка підпису вебхука
$expected = hash_hmac('sha256', $payload, $secret);

if (! hash_equals($expected, $request->header('X-Signature'))) {
    abort(403);
}

Де це потрібно: скрізь, де рядок від користувача порівнюється із секретом - підписи вебхуків, API-токени, коди підтвердження, CSRF-токени.

Що варто знати:

  • Першим аргументом іде відомий рядок, другим - отриманий від користувача.
  • Довжину hash_equals не приховує: рядки різної довжини дають false одразу. Тому порівнюють хеші чи HMAC фіксованої довжини, а не сирі секрети.
  • Для паролів не потрібен ні ===, ні hash_equals: password_verify() уже порівнює безпечно.

Laravel використовує hash_equals усередині - наприклад, у перевірці CSRF-токена й підписаних URL.

Докладніше в документації: hash_equals

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання