Haszowanie hasła

W celu zapewnienia bezpieczeństwa naszych użytkowników nie przechowujemy ich haseł w czytelnej formie, a jedynie przechowujemy odcisk palca (tzw. hash). Z odcisku palca nie da się odtworzyć oryginalnej postaci hasła. Ważne jest, aby do stworzenia odcisku palca użyć bezpiecznego algorytmu. Pomoże nam w tym klasa Nette\Security\Passwords.

Instalacja i wymagania

Framework automatycznie dodaje usługę taką jak Nette\Security\Passwords do kontenera DI pod nazwą security.passwords, do której możesz uzyskać dostęp, zlecając jej przekazanie za pomocą zastrzyku zależności.

use Nette\Security\Passwords;

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

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

Wybieramy, jaki bezpieczny algorytm generowania hashów zastosować i konfigurujemy jego parametry.

Domyślnie jest to PASSWORD_DEFAULT, więc wybór algorytmu pozostawiamy PHP. Algorytm ten może ulec zmianie w nowszych wersjach PHP, jeśli pojawią się nowsze, silniejsze algorytmy haszujące. Dlatego należy mieć świadomość, że długość wynikowego hasha może się zmienić i należy go przechowywać w sposób, który może pomieścić wystarczająco dużo znaków, 255 to zalecana szerokość.

Przykład ustawienia prędkości haszowania algorytmu bcrypt poprzez zmianę parametru cost: (w 2020 roku domyślnie 10, haszowanie hasła trwa około 80ms, dla kosztu 11 jest to około 160ms, dla kosztu 12 jest to około 320ms, im wolniej tym lepsze zabezpieczenie, a prędkość 10–12 jest już uważana za wystarczające zabezpieczenie)

// budeme hesla hashovat 2^12 (2^cost) iteracemi algorytmu bcrypt
$passwords = new Passwords(PASSWORD_BCRYPT, ['cost' => 12]);

Wykorzystanie wstrzykiwania zależności:

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

hash(string $passwords): string

Generuje hash hasła.

$res = $passwords->hash($password); // Zahashuje heslo

Wynik, $res, to ciąg znaków, który oprócz samego hasha zawiera identyfikator użytego algorytmu, jego ustawienia oraz sól kryptograficzną (losowe dane zapewniające wygenerowanie innego hasha dla tego samego hasła). Dzięki temu jest on kompatybilny wstecz, na przykład w przypadku zmiany parametrów można zweryfikować hashe zapisane przy użyciu poprzednich ustawień. Cały ten wynik jest przechowywany w bazie danych, więc nie ma potrzeby przechowywania soli czy ustawień osobno.

verify(string $password, string $hash)bool

Ustalenie, czy hasło pasuje do podanego odcisku palca. $hash pobranie z bazy danych według podanej nazwy użytkownika lub adresu e-mail.

if ($passwords->verify($password, $hash)) {
	// poprawne hasło
}

needsRehash(string $hash): bool

Uzyskuje informację czy hash pasuje do opcji określonych w konstruktorze.

Przydatne, gdy na przykład zmieniasz szybkość haszowania. Sprawdzi się w stosunku do zapisanych ustawień i jeśli needsRehash() zwróci true, to musisz odtworzyć hash, tym razem z nowymi parametrami i ponownie zapisać go w bazie danych. W ten sposób zapisane hashe są automatycznie “aktualizowane”, gdy użytkownicy się logują.

if ($passwords->needsRehash($hash)) {
	$hash = $passwords->hash($password);
	// uložit $hash do databáze
}
wersja: 4.0