Passwort-Hashing

Um die Sicherheit unserer Benutzer zu gewährleisten, speichern wir ihre Passwörter nicht im Klartext, sondern nur deren Hash (sog. Fingerabdruck). Aus dem Hash lässt sich die ursprüngliche Form des Passworts nicht rekonstruieren. Es ist wichtig, einen sicheren Algorithmus zur Erstellung des Hashs zu verwenden. Dabei hilft uns die Klasse Nette\Security\Passwords.

Installation und Anforderungen

Das Framework fügt dem DI-Container automatisch einen Dienst vom Typ Nette\Security\Passwords unter dem Namen security.passwords hinzu, auf den Sie zugreifen können, indem Sie ihn sich mittels Dependency Injection übergeben lassen.

use Nette\Security\Passwords;

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

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

Wir wählen aus, welcher sichere Algorithmus zur Generierung des Hashs verwendet werden soll, und konfigurieren seine Parameter.

Als Standard wird PASSWORD_DEFAULT verwendet, d.h., die Wahl des Algorithmus wird PHP überlassen. Der Algorithmus kann sich in neueren PHP-Versionen ändern, wenn neuere, stärkere Hashing-Algorithmen verfügbar werden. Daher sollten Sie sich bewusst sein, dass sich die Länge des resultierenden Hashs ändern kann, und Sie sollten ihn so speichern, dass er genügend Zeichen aufnehmen kann. 255 ist die empfohlene Breite.

Beispiel für die Einstellung der Hashing-Geschwindigkeit des bcrypt-Algorithmus durch Änderung des cost-Parameters: (Im Jahr 2020 ist der Standardwert 10, das Hashing eines Passworts dauert etwa 80 ms, bei cost 11 sind es ca. 160 ms, bei cost 12 etwa 320 ms. Je langsamer, desto besser der Schutz, wobei eine Geschwindigkeit von 10–12 bereits als ausreichender Schutz gilt.)

// wir werden Passwörter mit 2^12 (2^cost) Iterationen des bcrypt-Algorithmus hashen
$passwords = new Passwords(PASSWORD_BCRYPT, ['cost' => 12]);

Mittels Dependency Injection:

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

hash (string $password): string

Generiert den Hash des Passworts.

$hash = $passwords->hash($password); // Hasht das Passwort

Das Ergebnis $hash ist eine Zeichenkette, die neben dem eigentlichen Hash auch den Bezeichner des verwendeten Algorithmus, seine Einstellungen und das kryptografische Salt (zufällige Daten, die sicherstellen, dass für dasselbe Passwort ein anderer Hash generiert wird) enthält. Es ist also abwärtskompatibel. Wenn Sie beispielsweise die Parameter ändern, können auch Hashes überprüft werden, die mit den vorherigen Einstellungen gespeichert wurden. Das gesamte Ergebnis wird in der Datenbank gespeichert, sodass Salt oder Einstellungen nicht separat gespeichert werden müssen.

verify (string $password, string $hash)bool

Stellt fest, ob das gegebene Passwort dem gegebenen Hash entspricht. $hash erhalten Sie aus der Datenbank anhand des eingegebenen Benutzernamens oder der E-Mail-Adresse.

if ($passwords->verify($password, $hash)) {
	// korrektes Passwort
}

needsRehash (string $hash): bool

Stellt fest, ob der Hash den im Konstruktor angegebenen Optionen entspricht.

Dies ist nützlich, wenn Sie beispielsweise die Hashing-Geschwindigkeit ändern. Die Überprüfung erfolgt gemäß den gespeicherten Einstellungen, und wenn needsRehash() true zurückgibt, muss der Hash erneut erstellt werden, diesmal mit den neuen Parametern, und erneut in der Datenbank gespeichert werden. Auf diese Weise werden gespeicherte Hashes beim Anmelden der Benutzer automatisch “aktualisiert”.

if ($passwords->needsRehash($hash)) {
	$hash = $passwords->hash($password);
	// $hash in der Datenbank speichern
}
Version: 4.0