Nette Documentation Preview

syntax
Hashowanie haseł
****************

.[perex]
Żeby zapewnić bezpieczeństwo naszym użytkownikom, nigdy nie przechowujemy ich haseł w czytelnej postaci, tylko przechowujemy ich odcisk (tak zwany hash). Z hasha nie da się odtworzyć pierwotnego hasła. Ważne jest użycie bezpiecznego algorytmu do jego utworzenia. Pomaga nam w tym klasa [api:Nette\Security\Passwords].

→ [Instalacja i wymagania |@home#Instalacja]

Framework automatycznie dodaje do kontenera DI usługę typu `Nette\Security\Passwords` pod nazwą `security.passwords`. Uzyskasz ją, pozwalając sobie ją przekazać przez [wstrzykiwanie zależności |dependency-injection:passing-dependencies].

```php
use Nette\Security\Passwords;

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


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

Wybieramy, którego [bezpiecznego algorytmu|https://www.php.net/manual/en/password.constants.php] użyć do wygenerowania hasha, i konfigurujemy jego parametry.

Domyślnie używany jest `PASSWORD_DEFAULT`, czyli wybór algorytmu pozostawiony jest PHP. Algorytm może się zmienić w nowszych wersjach PHP, jeśli pojawią się nowsze, silniejsze algorytmy hashujące. Dlatego powinieneś mieć świadomość, że długość wynikowego hasha może się zmienić, i przechowywać go w sposób pozwalający pomieścić dostatecznie dużo znaków; zalecana szerokość to 255.

Przykład ustawienia szybkości hashowania dla algorytmu bcrypt przez zmianę parametru cost: (w 2020 domyślną wartością jest 10, hashowanie hasła zajmuje mniej więcej 80 ms; dla cost 11 to ok. 160 ms, dla cost 12 ok. 320 ms; im wolniej, tym lepsza ochrona, przy czym szybkość 10-12 jest już uznawana za wystarczającą ochronę)

```php
// hasła będziemy hashować 2^12 (2^cost) iteracjami algorytmu bcrypt
$passwords = new Passwords(PASSWORD_BCRYPT, ['cost' => 12]);
```

Przy użyciu wstrzykiwania zależności:
```neon
services:
	security.passwords: Nette\Security\Passwords(::PASSWORD_BCRYPT, [cost: 12])
```


static bcrypt(?int $cost=null): Passwords .[method]{data-version:3.2.6}
=======================================================================

Tworzy instancję skonfigurowaną dla algorytmu bcrypt. Parametr `$cost` ustawia opisaną wyżej szybkość hashowania; jeśli go pominiesz, użyta zostanie wartość domyślna PHP.

```php
$passwords = Passwords::bcrypt(12);
```


static argon2id(?int $memoryCost=null, ?int $timeCost=null, ?int $threads=null): Passwords .[method]{data-version:3.2.6}
========================================================================================================================

Tworzy instancję skonfigurowaną dla algorytmu Argon2id. Pominięte parametry pozostają na wartościach domyślnych PHP. Jeśli PHP zostało zbudowane bez wsparcia dla Argon2, metoda rzuca `Nette\NotSupportedException`.

```php
$passwords = Passwords::argon2id(memoryCost: 1 << 17, timeCost: 4);
```


hash(string $password): string .[method]
========================================

Generuje hash hasła.

```php
$res = $passwords->hash($password); // Zahashuje hasło
```

Wynik `$res` to ciąg, który oprócz samego hasha zawiera identyfikator użytego algorytmu, jego ustawienia i sól kryptograficzną (losowe dane zapewniające, że dla tego samego hasła powstanie inny hash). Jest więc wstecznie kompatybilny; jeśli na przykład zmienisz parametry, hashe zapisane przy poprzednich ustawieniach da się nadal zweryfikować. Cały ten wynik zapisujemy do bazy danych, więc nie trzeba osobno przechowywać soli ani ustawień.


verify(string $password, string $hash): bool .[method]
======================================================

Ustala, czy podane hasło odpowiada podanemu hashowi. `$hash` uzyskaj z bazy danych według wpisanej nazwy użytkownika albo adresu e-mail.

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


needsRehash(string $hash): bool .[method]
=========================================

Ustala, czy hash odpowiada opcjom podanym w konstruktorze.

Przydaje się to na przykład wtedy, gdy zmieniasz cost hashowania. Weryfikacja odbywa się według zapisanych ustawień, a jeśli `needsRehash()` zwróci `true`, trzeba utworzyć hash na nowo, tym razem z nowymi parametrami, i ponownie zapisać go w bazie danych. Automatycznie "aktualizuje" to zapisane hashe przy logowaniu użytkowników.

```php
if ($passwords->needsRehash($hash)) {
	$hash = $passwords->hash($password);
	// zapisz $hash do bazy danych
}
```

Hashowanie haseł

Żeby zapewnić bezpieczeństwo naszym użytkownikom, nigdy nie przechowujemy ich haseł w czytelnej postaci, tylko przechowujemy ich odcisk (tak zwany hash). Z hasha nie da się odtworzyć pierwotnego hasła. Ważne jest użycie bezpiecznego algorytmu do jego utworzenia. Pomaga nam w tym klasa Nette\Security\Passwords.

Instalacja i wymagania

Framework automatycznie dodaje do kontenera DI usługę typu Nette\Security\Passwords pod nazwą security.passwords. Uzyskasz ją, pozwalając sobie ją przekazać przez wstrzykiwanie zależności.

use Nette\Security\Passwords;

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

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

Wybieramy, którego bezpiecznego algorytmu użyć do wygenerowania hasha, i konfigurujemy jego parametry.

Domyślnie używany jest PASSWORD_DEFAULT, czyli wybór algorytmu pozostawiony jest PHP. Algorytm może się zmienić w nowszych wersjach PHP, jeśli pojawią się nowsze, silniejsze algorytmy hashujące. Dlatego powinieneś mieć świadomość, że długość wynikowego hasha może się zmienić, i przechowywać go w sposób pozwalający pomieścić dostatecznie dużo znaków; zalecana szerokość to 255.

Przykład ustawienia szybkości hashowania dla algorytmu bcrypt przez zmianę parametru cost: (w 2020 domyślną wartością jest 10, hashowanie hasła zajmuje mniej więcej 80 ms; dla cost 11 to ok. 160 ms, dla cost 12 ok. 320 ms; im wolniej, tym lepsza ochrona, przy czym szybkość 10–12 jest już uznawana za wystarczającą ochronę)

// hasła będziemy hashować 2^12 (2^cost) iteracjami algorytmu bcrypt
$passwords = new Passwords(PASSWORD_BCRYPT, ['cost' => 12]);

Przy użyciu wstrzykiwania zależności:

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

static bcrypt(?int $cost=null): Passwords

Tworzy instancję skonfigurowaną dla algorytmu bcrypt. Parametr $cost ustawia opisaną wyżej szybkość hashowania; jeśli go pominiesz, użyta zostanie wartość domyślna PHP.

$passwords = Passwords::bcrypt(12);

static argon2id(?int $memoryCost=null, ?int $timeCost=null, ?int $threads=null): Passwords

Tworzy instancję skonfigurowaną dla algorytmu Argon2id. Pominięte parametry pozostają na wartościach domyślnych PHP. Jeśli PHP zostało zbudowane bez wsparcia dla Argon2, metoda rzuca Nette\NotSupportedException.

$passwords = Passwords::argon2id(memoryCost: 1 << 17, timeCost: 4);

hash(string $password): string

Generuje hash hasła.

$res = $passwords->hash($password); // Zahashuje hasło

Wynik $res to ciąg, który oprócz samego hasha zawiera identyfikator użytego algorytmu, jego ustawienia i sól kryptograficzną (losowe dane zapewniające, że dla tego samego hasła powstanie inny hash). Jest więc wstecznie kompatybilny; jeśli na przykład zmienisz parametry, hashe zapisane przy poprzednich ustawieniach da się nadal zweryfikować. Cały ten wynik zapisujemy do bazy danych, więc nie trzeba osobno przechowywać soli ani ustawień.

verify(string $password, string $hash)bool

Ustala, czy podane hasło odpowiada podanemu hashowi. $hash uzyskaj z bazy danych według wpisanej nazwy użytkownika albo adresu e-mail.

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

needsRehash(string $hash)bool

Ustala, czy hash odpowiada opcjom podanym w konstruktorze.

Przydaje się to na przykład wtedy, gdy zmieniasz cost hashowania. Weryfikacja odbywa się według zapisanych ustawień, a jeśli needsRehash() zwróci true, trzeba utworzyć hash na nowo, tym razem z nowymi parametrami, i ponownie zapisać go w bazie danych. Automatycznie „aktualizuje“ to zapisane hashe przy logowaniu użytkowników.

if ($passwords->needsRehash($hash)) {
	$hash = $passwords->hash($password);
	// zapisz $hash do bazy danych
}