Хешування паролів

Для забезпечення безпеки наших користувачів ми ніколи не зберігаємо їхні паролі у відкритому вигляді, натомість ми зберігаємо хеш пароля. Хешування не є оборотною операцією, пароль не може бути відновлений. Однак пароль можна зламати, і щоб зробити злом якомога важчим, ми повинні використовувати безпечний алгоритм. Клас Nette\Security\Passwords допоможе нам у цьому.

→ Встановлення та вимоги

Фреймворк автоматично додає сервіс Nette\Security\Passwords у контейнер DI під іменем security.passwords, який ви отримуєте, передаючи його за допомогою ін'єкції залежностей:

use Nette\Security\Passwords;

class Foo
{
	public function __construct(
		private Passwords $passwords,
	) {
	}
}

__construct($algo=PASSWORD_DEFAULT, array $options=[])string

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

За замовчуванням використовується PASSWORD_DEFAULT, тому вибір алгоритму залишається за PHP. Алгоритм може змінитися в нових релізах PHP, коли підтримуватимуться новіші та сильніші алгоритми хешування. Тому ви повинні знати, що довжина результуючого хешу може змінитися. Тому ви повинні зберігати результуючий хеш таким чином, щоб він міг зберігати достатню кількість символів, рекомендована ширина 255.

Ось як можна використовувати алгоритм bcrypt і змінити швидкість хешування за допомогою параметра cost від значення за замовчуванням 10. У 2020 році за вартості 10 хешування одного пароля займає приблизно 80 мс, за вартості 11 – 160 мс, за вартості 12 – 320 мс, шкала логарифмічна. Чим повільніше, тим краще, вартість 10–12 вважається досить повільною для більшості випадків використання:

// будемо хешувати паролі за 2^12 (2^cost) ітерацій алгоритму bcrypt
$passwords = new Passwords(PASSWORD_BCRYPT, ['cost' => 12]);

З ін'єкцією залежностей:

services:
	security.passwords: Nette\Security\Passwords(::PASSWORD_BCRYPT, [cost: 12])

hash(string $passwords): string

Генерує хеш пароля.

$res = $passwords->hash($password); // Хешує пароль

Результат $res являє собою рядок, який, крім самого хеша, містить ідентифікатор використовуваного алгоритму, його налаштування і криптографічну сіль (випадкові дані, що гарантують, що для одного і того ж пароля буде згенеровано інший хеш). Таким чином, забезпечується зворотна сумісність, наприклад, у разі зміни параметрів можна перевірити хеші, збережені з використанням попередніх налаштувань. Весь результат зберігається в базі даних, тому немає необхідності зберігати сіль або налаштування окремо.

verify(string $password, string $hash)bool

З'ясовує, чи збігається заданий пароль із заданим хешем. Отримати $hash з бази даних за ім'ям користувача або адресою електронної пошти.

if ($passwords->verify($password, $hash)) {
	// Правильний пароль
}

needsRehash(string $hash): bool

З'ясовує, чи відповідає хеш параметрам, заданим у конструкторі.

Використовуйте цей метод, коли ви, наприклад, змінюєте параметри хеша. Перевірка пароля буде використовувати параметри, збережені разом із хешем, і якщо needsRehash() поверне true, вам доведеться знову обчислити хеш, цього разу з оновленими параметрами, і знову зберегти його в базі даних. Це гарантує, що хеші паролів будуть автоматично “оновлюватися” при вході користувачів у систему.

if ($passwords->needsRehash($hash)) {
	$hash = $passwords->hash($password);
	// зберігаємо $hash в базу даних
}
версію: 4.0