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.
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
}