Sicheres Hashing in PHP

PHP bringt prinzipiell alles mit, um anständiges Hashing zu betreiben. bcrypt ist der Way To Go, aber auch ohne bcrypt kann man mit vernünftigem Einsatz der vorhanden Hashing-Algorithmen (Iterationen + Salt) gut zurechtkommen – Symfony machts im MessageDigestPasswordEncoder.php richtig. Hauptproblem ist aber, dass vom Durchschnitts-Nutzer zuviel Wissen abverlangt wird, um wirklich sicheres Hashing zu betreiben. Deswegen schickt sich jetzt in PHP 5.5 eine Hashing-Library an, es besser zu machen. Bis es soweit ist und die Funktionalität im Core ankommt, gibt es für PHP >= 5.3.7 eine Compatiblity-Library, die das Verhalten der kommenden Hashing-Funktionen nachbildet.

Die Signaturen der Funktionen aus der Compat-Library sind wie folgt: password_hash($password, $algo, $options = array())

Wobei im Options-Array der cost-Factor von bcrypt und das salt spezifiziert wird. Verwendung dann wie folgt:

$password = "foo"; $opts = array("cost" => 15, "salt" => "this is my salt, that I use for salting"); $hash = password_hash($password, PASSWORD_BCRYPT, $opts); //$2y$12$dGhpcyBpcyBteSBzYWx0L.QLYHdN06l.OhslYu9VilOYVwFApNezu 

Weiter gehts mit password_get_info:

password_get_info($hash) 

Da der Cost-Faktor und der Hashing-Algorithmus mit im Hash gespeichert wird (was KEIN Sicherheitsverlust ist, da es nur um das Erschweren von Rainbowtable-Angriffen geht), können wir die Infos natürlich auch wieder auslesen:

$hash = "$2y$12$dGhpcyBpcyBteSBzYWx0L.QLYHdN06l.OhslYu9VilOYVwFApNezu"; print_r(password_get_info($hash)); /* Array (     [algo] => 1     [algoName] => bcrypt     [options] => Array 	( 		[cost] => 12 	) ) */ 

Darauf aufbauend lässt sich auch ermitteln, ob ein Passwort neu gehasht werden muss, etwa weil sich der Cost-Faktor geändert hat.

password_needs_rehash($hash, $algo, array $options = array()) 

Wichtig: Das salt wird hierbei nicht beachtet.

$opts = array("cost" => 13); var_dump(password_needs_rehash($hash, PASSWORD_BCRYPT, $opts)); //bool(true) 

Und natürlich die Verifikation, die einfacher kaum ausfallen könnte:

password_verify($password, $hash) 

In der Praxis:

var_dump(password_verify("foo", '$2y$15$dGhpcyBpcyBteSBzYWx0L.TvUDgIgEuPSAJGRCDlJKS8ZI/HaKF4S')); //bool(true) 

Das vollständige RFC, weitere Beispiele und eine umfassende Erkärung gibts im PHP-Wiki. Eine gute Entwicklung!


Deprecated: Directive 'allow_url_include' is deprecated in Unknown on line 0