Hashing gesel

Zaradi varnosti naših uporabnikov njihovih gesel nikoli ne shranjujemo v obliki navadnega besedila, temveč shranjujemo njihov hash. Hashing ni reverzibilna operacija, gesla ni mogoče obnoviti. Geslo pa je mogoče razbiti in da bi bilo razbijanje čim težje, moramo uporabiti varen algoritem. Pri tem nam bo pomagal razred Nette\Security\Passwords.

Namestitev in zahteve

Ogrodje samodejno doda storitev Nette\Security\Passwords v vsebnik DI pod imenom security.passwords, ki jo dobite tako, da jo posredujete z uporabo vbrizgavanja odvisnosti:

use Nette\Security\Passwords;

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

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

Izbere, kateri varni algoritem se uporablja za hashanje, in kako ga konfigurirati.

Privzeto je PASSWORD_DEFAULT, zato je izbira algoritma prepuščena PHP. Algoritem se lahko spremeni v novejših izdajah PHP, ko bodo podprti novejši in močnejši algoritmi za hashanje. Zato se morate zavedati, da se lahko dolžina dobljenega hasha spremeni. Zato morate nastali hash shraniti tako, da lahko shranite dovolj znakov, pri čemer je priporočena širina 255.

Tako bi uporabili algoritem bcrypt in spremenili hitrost hashanja s parametrom cost s privzete vrednosti 10. V letu 2020 s stroški 10 hashanje enega gesla traja približno 80 ms, s stroški 11 traja 160 ms, s stroški 12 nato 320 ms, lestvica je logaritemska. Čim počasneje, tem bolje, strošek 10–12 velja za dovolj počasnega za večino primerov uporabe:

// gesla bomo hashali z 2^12 (2^cost) iteracijami algoritma bcrypt
$passwords = new Passwords(PASSWORD_BCRYPT, ['cost' => 12]);

Z vbrizgavanjem odvisnosti:

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

hash(string $passwords): string

Ustvari hash gesla.

$res = $passwords->hash($password); // geslo se zgoščuje.

Rezultat $res je niz, ki poleg samega hasha vsebuje identifikator uporabljenega algoritma, njegove nastavitve in kriptografsko sol (naključni podatki, ki zagotavljajo, da se za isto geslo generira drugačen hash). Zato je združljiv za nazaj, na primer, če spremenite parametre, lahko preverite hashe, shranjene s prejšnjimi nastavitvami. Celoten rezultat je shranjen v zbirki podatkov, zato soli ali nastavitev ni treba shranjevati ločeno.

verify(string $password, string $hash)bool

Ugotovi, ali se dano geslo ujema z danim hashem. Pridobi $hash iz zbirke podatkov po uporabniškem imenu ali e-poštnem naslovu.

if ($passwords->verify($password, $hash)) {
	// Pravilno geslo
}

needsRehash(string $hash): bool

Ugotovi, ali se hash ujema z možnostmi, podanimi v konstruktorju.

To metodo uporabite, kadar na primer spreminjate parametre hashanja. Pri preverjanju gesla bodo uporabljeni parametri, shranjeni skupaj s hashem, in če needsRehash() vrne true, morate hash ponovno izračunati, tokrat s posodobljenimi parametri, in ga ponovno shraniti v zbirko podatkov. S tem zagotovite, da se bodo gesla hashe samodejno “nadgradila”, ko se bodo uporabniki vpisovali v sistem.

if ($passwords->needsRehash($hash)) {
	$hash = $passwords->hash($password);
	// shranjevanje $hash v zbirko podatkov
}
različica: 4.0