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
}