Passwort-Hashing
Um die Sicherheit unserer Benutzer zu gewährleisten, speichern wir ihre Passwörter nie im Klartext, sondern nur als Hash. Das Hashing ist kein umkehrbarer Vorgang, das Kennwort kann nicht wiederhergestellt werden. Das Passwort kann jedoch geknackt werden, und um das Knacken so schwer wie möglich zu machen, müssen wir einen sicheren Algorithmus verwenden. Die Klasse Nette\Security\Passwords wird uns dabei helfen.
→ Installation und Anforderungen
Das Framework fügt dem DI-Container automatisch einen Dienst Nette\Security\Passwords
unter dem Namen
security.passwords
hinzu, den man durch Übergabe mittels Dependency Injection erhält:
use Nette\Security\Passwords;
class Foo
{
public function __construct(
private Passwords $passwords,
) {
}
}
__construct($algo=PASSWORD_DEFAULT, array $options=[]): string
Wählt aus, welcher sichere Algorithmus für das Hashing verwendet wird und wie er konfiguriert werden soll.
Die Vorgabe ist PASSWORD_DEFAULT
, so dass die Wahl des Algorithmus PHP überlassen wird. Der Algorithmus kann sich
in neueren PHP-Versionen ändern, wenn neuere, stärkere Hashing-Algorithmen unterstützt werden. Sie sollten sich daher bewusst
sein, dass sich die Länge des resultierenden Hashes ändern kann. Daher sollten Sie den resultierenden Hash in einer Weise
speichern, die genügend Zeichen speichern kann, 255 ist die empfohlene Breite.
So würden Sie den bcrypt-Algorithmus verwenden und die Hash-Geschwindigkeit mit dem Parameter cost von der Standardeinstellung 10 ändern. Im Jahr 2020 dauert das Hashing eines Kennworts mit Kosten 10 etwa 80 ms, mit Kosten 11 160 ms und mit Kosten 12 320 ms, die Skala ist logarithmisch. Je langsamer, desto besser, Kosten 10–12 werden als langsam genug für die meisten Anwendungsfälle angesehen:
// Wir werden Passwörter mit 2^12 (2^cost) Iterationen des bcrypt-Algorithmus hashen
$passwords = new Passwords(PASSWORD_BCRYPT, ['cost' => 12]);
Mit Dependency Injection:
services:
security.passwords: Nette\Security\Passwords(::PASSWORD_BCRYPT, [cost: 12])
hash(string $passwords): string
Erzeugt den Hash des Passworts.
$res = $passwords->hash($password); // Hashes des Passworts
Das Ergebnis $res
ist eine Zeichenkette, die neben dem Hash selbst auch die Kennung des verwendeten Algorithmus,
seine Einstellungen und das kryptografische Salt (Zufallsdaten, die sicherstellen, dass für dasselbe Kennwort ein anderer Hash
erzeugt wird) enthält. Es ist daher rückwärtskompatibel, d. h., wenn Sie die Parameter ändern, können die mit den vorherigen
Einstellungen gespeicherten Hashes überprüft werden. Das gesamte Ergebnis wird in der Datenbank gespeichert, so dass es nicht
notwendig ist, Salt oder Einstellungen separat zu speichern.
verify(string $password, string $hash): bool
Findet heraus, ob das angegebene Passwort mit dem angegebenen Hash übereinstimmt. Holt die $hash
aus der
Datenbank nach Benutzernamen oder E-Mail Adresse.
if ($passwords->verify($password, $hash)) {
// Richtiges Passwort
}
needsRehash(string $hash): bool
Findet heraus, ob der Hash mit den im Konstruktor angegebenen Optionen übereinstimmt.
Verwenden Sie diese Methode, wenn Sie zum Beispiel Hash-Parameter ändern. Die Passwortüberprüfung verwendet die mit dem Hash
gespeicherten Parameter, und wenn needsRehash()
true zurückgibt, müssen Sie den Hash erneut berechnen, diesmal mit
den aktualisierten Parametern, und ihn erneut in der Datenbank speichern. Dadurch wird sichergestellt, dass die Hashes der
Passwörter automatisch „aktualisiert“ werden, wenn sich die Benutzer anmelden.
if ($passwords->needsRehash($hash)) {
$hash = $passwords->hash($password);
// $hash in der Datenbank speichern
}