Hashování hesel
Abychom zajistili bezpečnost našich uživatelů, neukládáme jejich hesla v čitelné podobě, ale uložíme si pouze otisk (tzv. hash). Z otisku nelze zpětně zrekonstruovat původní podobu hesla. Je důležité použít bezpečný algoritmus, kterým otisk vytvoříme. S tím nám pomůže statická třída Nette\Security\Passwords.
Instalace:
composer require nette/utils
Všechny příklady předpokládají vytvořený alias:
use Nette\Security\Passwords;
hash(string $passwords, ?array $options=null): string
Vygeneruje hash hesla pomocí moderního algoritmu bcrypt. Můžeme určit parametr cost
z rozsahu 4–31, který
udává kolik iterací algoritmu má proběhnout a měníte tím rychlost hashování. Pokud parametr neurčíme, bude použita
výchozí hodnota 10
.
V roce 2020 s hodnotou cost 10 trvá hashování hesla velmi zhruba 80ms, pro cost 11 je to cca 160ms, pro cost 12 zhruba 320ms, čím pomalejší, tím lepší ochrana, přičemž rychlost 10–12 se již považuje za ochranu dostatečnou.
$hash = Passwords::hash($password); // Zahashuje heslo
$hash = Passwords::hash($password, ['cost' => 12]); // Zahashuje heslo 2^12 iteracemi algoritmu bcrypt
Výsledek $hash
obsahuje identifikátor použitého algoritmu i jeho nastavení, kryptografickou sůl i samotný
hash. Je tedy zpětně kompatibilní, když například změníte parametry, tak i hashe uložené s použitím předchozího
nastavení půjdou ověřit. Celý tento výsledek se ukládá do databáze, takže není potřeba ukládat sůl nebo nastavení
zvlášť.
verify(string $password, string $hash): bool
Zjistí, zda dané heslo odpovídá danému otisku. $hash
získejte z databáze podle zadaného uživatelského
jména nebo e-mailové adresy.
if (Passwords::verify($password, $hash)) {
// správné heslo
}
needsRehash(string $password, ?array $options=null): bool
Zjistí, zda hash odpovídá zadaným volbám. Můžeme nastavit cost
v rozsahu 4–31, který udává kolik
iterací algoritmu má proběhnout. Pokud parametr neurčíme, bude použita výchozí hodnota 10
.
Hodí se použít ve chvíli, kdy např. měníte rychlost hashování. Ověření proběhne podle uloženého nastavení a
pokud needsRehash()
vrátí true
, tak je potřeba znovu vytvořit hash, tentokrát s novými parametry,
a uložit ho znovu do databáze. Takto se automaticky „upgradují“ uložené hashe při přihlašování uživatelů.
if (Passwords::needsRehash($hash, $options)) {
$hash = Passwords::hash($password, $options);
// uložit $hash do databáze
}