{"id":651,"date":"2012-10-11T10:00:01","date_gmt":"2012-10-11T08:00:01","guid":{"rendered":"https:\/\/d-mueller.de\/blog\/?p=651"},"modified":"2016-01-11T23:51:10","modified_gmt":"2016-01-11T22:51:10","slug":"sicheres-hashing-in-php","status":"publish","type":"post","link":"https:\/\/d-mueller.de\/blog\/sicheres-hashing-in-php\/","title":{"rendered":"Sicheres Hashing in PHP"},"content":{"rendered":"<p>PHP bringt prinzipiell alles mit, um anst\u00e4ndiges Hashing zu betreiben. <a href=\"http:\/\/www.phpgangsta.de\/schoener-hashen-mit-bcrypt\">bcrypt<\/a> ist der Way To Go, aber auch ohne bcrypt kann man mit vern\u00fcnftigem Einsatz der vorhanden Hashing-Algorithmen (Iterationen + Salt) gut zurechtkommen &#8211; <a href=\"https:\/\/github.com\/symfony\/symfony\/blob\/master\/src\/Symfony\/Component\/Security\/Core\/Encoder\/MessageDigestPasswordEncoder.php\">Symfony machts im <i>MessageDigestPasswordEncoder.php<\/i> richtig<\/a>. 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\u00e4t im Core ankommt, gibt es f\u00fcr PHP >= 5.3.7 eine <a href=\"https:\/\/github.com\/ircmaxell\/password_compat\">Compatiblity-Library<\/a>, die das Verhalten der kommenden Hashing-Funktionen nachbildet.<\/p>\n<p>Die Signaturen der Funktionen aus der Compat-Library sind wie folgt: <\/p>\n<pre data-enlighter-language=\"enlighter\" class=\"EnlighterJSRAW\">password_hash($password, $algo, $options = array())<\/pre>\n<p>Wobei im Options-Array der cost-Factor von bcrypt und das salt spezifiziert wird. Verwendung dann wie folgt:<\/p>\n<pre data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">\r\n$password = &quot;foo&quot;;\r\n$opts = array(&quot;cost&quot; =&gt; 15, &quot;salt&quot; =&gt; &quot;this is my salt, that I use for salting&quot;);\r\n$hash = password_hash($password, PASSWORD_BCRYPT, $opts); \/\/$2y$12$dGhpcyBpcyBteSBzYWx0L.QLYHdN06l.OhslYu9VilOYVwFApNezu\r\n<\/pre>\n<p>Weiter gehts mit <b>password_get_info<\/b>:<\/p>\n<pre data-enlighter-language=\"enlighter\" class=\"EnlighterJSRAW\">\r\npassword_get_info($hash)\r\n<\/pre>\n<p>Da der Cost-Faktor und der Hashing-Algorithmus mit im Hash gespeichert wird (was <b>KEIN<\/b> Sicherheitsverlust ist, da es nur um das Erschweren von Rainbowtable-Angriffen geht), k\u00f6nnen wir die Infos nat\u00fcrlich auch wieder auslesen:<\/p>\n<pre data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">\r\n$hash = &quot;$2y$12$dGhpcyBpcyBteSBzYWx0L.QLYHdN06l.OhslYu9VilOYVwFApNezu&quot;;\r\nprint_r(password_get_info($hash));\r\n\/*\r\nArray\r\n(\r\n    [algo] =&gt; 1\r\n    [algoName] =&gt; bcrypt\r\n    [options] =&gt; Array\r\n\t(\r\n\t\t[cost] =&gt; 12\r\n\t)\r\n)\r\n*\/\r\n<\/pre>\n<p>Darauf aufbauend l\u00e4sst sich auch ermitteln, ob ein Passwort neu gehasht werden muss, etwa weil sich der Cost-Faktor ge\u00e4ndert hat.<\/p>\n<pre data-enlighter-language=\"enlighter\" class=\"EnlighterJSRAW\">\r\npassword_needs_rehash($hash, $algo, array $options = array())\r\n<\/pre>\n<p>Wichtig: Das salt wird hierbei nicht beachtet.<\/p>\n<pre data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">\r\n$opts = array(&quot;cost&quot; =&gt; 13);\r\nvar_dump(password_needs_rehash($hash, PASSWORD_BCRYPT, $opts)); \/\/bool(true)\r\n<\/pre>\n<p>Und nat\u00fcrlich die Verifikation, die einfacher kaum ausfallen k\u00f6nnte: <\/p>\n<pre data-enlighter-language=\"enlighter\" class=\"EnlighterJSRAW\">\r\npassword_verify($password, $hash)\r\n<\/pre>\n<p>In der Praxis:<\/p>\n<pre data-enlighter-language=\"php\" class=\"EnlighterJSRAW\">\r\nvar_dump(password_verify(&quot;foo&quot;, &#039;$2y$15$dGhpcyBpcyBteSBzYWx0L.TvUDgIgEuPSAJGRCDlJKS8ZI\/HaKF4S&#039;)); \/\/bool(true)\r\n<\/pre>\n<p>Das vollst\u00e4ndige RFC, weitere Beispiele und eine umfassende Erk\u00e4rung gibts <a href=\"https:\/\/wiki.php.net\/rfc\/password_hash\">im PHP-Wiki<\/a>. Eine gute Entwicklung!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>PHP bringt prinzipiell alles mit, um anst\u00e4ndiges Hashing zu betreiben. bcrypt ist der Way To Go, aber auch ohne bcrypt kann man mit vern\u00fcnftigem Einsatz der vorhanden Hashing-Algorithmen (Iterationen + Salt) gut zurechtkommen &#8211; Symfony machts im MessageDigestPasswordEncoder.php richtig. Hauptproblem &hellip; <a href=\"https:\/\/d-mueller.de\/blog\/sicheres-hashing-in-php\/\">Weiterlesen <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,6,3],"tags":[],"class_list":["post-651","post","type-post","status-publish","format-standard","hentry","category-php","category-security","category-webdev"],"_links":{"self":[{"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/posts\/651","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/comments?post=651"}],"version-history":[{"count":0,"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/posts\/651\/revisions"}],"wp:attachment":[{"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/media?parent=651"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/categories?post=651"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/d-mueller.de\/blog\/wp-json\/wp\/v2\/tags?post=651"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}