Argon2 ist ein modernes Passwort-Hashing-Verfahren. Argon2 wurde 2014 entwickelt und hat 2015 die viel beachtete Password Hashing Competition gewonnen. Das Entwurfsziel des Algorithmus ist die intensive Nutzung von Ressourcen wie CPU und RAM, die per Parameter eingestellt werden können. Dadurch wird ein Angriff durch spezielle Hardware deutlich erschwert. Von Argon2 steht eine freie Implementierung auf Github zur Verfügung.
Argon2 wird in PHP seit der Version 7.2 unterstützt. Die Argon2-Unterstützung kann mit dem folgenden Befehl beim Kompilieren hinzugefügt werden:
./configure --with-password-argon2
Zum Generieren eines Hash in PHP wird die Funktion password_hash() verwendet. Es sollten auf jeden Fall immer die von PHP bereitgestellten Funktionen verwendet werden, da hier bestimmte Sicherheitsmerkmale bereits integriert sind. Von Argon2 stehen verschiedene Varianten zur Verfügung, es wird empfohlen die Variante ARGON2ID einzusetzen.
Beim Aufruf können als Optionen ein Faktor für den Speicher, die Zeit und die Threads übergeben werden:
$options = [ 'memory_cost' => PASSWORD_ARGON2_DEFAULT_MEMORY_COST, 'time_cost' => PASSWORD_ARGON2_DEFAULT_TIME_COST, 'threads' => PASSWORD_ARGON2_DEFAULT_THREADS, ]; password_hash('test', PASSWORD_ARGON2ID, $options);
Die Standardwerte in PHP für Argon2 sind 1024 Kb (memory_cost), 2 (time_cost‘) und 2 (threads). Je höher diese Werte sind, umso mehr Ressourcen benötigt ein Angreifer um die Hashes zu berechnen. Je nach Bereich gibt es unterschiedliche Empfehlungen. Dabei kann eine einzelne Abfrage für die Entschlüsselung einer Festplatte deutlich mehr Ressourcen einsetzten, als für einen Login für viele Benutzer auf einem Webserver. Hier ein paar Beispiele:
- Krypto-Währungen: 0,1 s, mit einem Kern (p = 2), 256 MB RAM
- Backend-Server-Authentifizierung: 0,5 s, mit 4 Kernen (p = 8), 4 GB RAM
- Schlüsselableitung für Festplattenverschlüsselung: 3s, mit 2 Kernen (p = 4), 6 GB RAM
- Frontend-Server-Authentifizierung: 0,5 s, mit 2 Kernen (p = 4), 1 GB RAM
Diese Werte lassen sich allerdings nicht pauschal übernehmen, sondern müssen immer auf dem jeweiligen Produktivsystem getestet werden. Pauschal sollten immer doppelt so viele Threads, wie zur Verfügung stehende, CPU-Kerne verwendet werden. Bei den beiden Parametern für Speicher und Zeit kann solange experimentiert werden bis die Berechnung in einem akzeptablen Zeitraum durchgeführt wird. Mein Ziel ist es hier zwischen 0,3 und 0,4 Sekunden zu liegen:
password_hash("test", PASSWORD_ARGON2ID, ["memory_cost" => 128000, "time_cost" => 20, "threads" => 8]);
password_hash("test", PASSWORD_ARGON2ID, ["memory_cost" => 32000, "time_cost" => 60, "threads" => 8]);
Der komplette Code zum selbst Testen:
$start = microtime(true); $pwdhash = password_hash("test", PASSWORD_ARGON2ID, ["memory_cost" => 128000, "time_cost" => 20, "threads" => 8]); $time = microtime(true) - $start; echo "Berechnung: $time Sekunden
"; echo'Hash: '.$pwdhash;