{"id":2946,"date":"2020-06-02T10:54:02","date_gmt":"2020-06-02T17:54:02","guid":{"rendered":"https:\/\/www.wellgolly.com\/?p=2946"},"modified":"2020-06-02T10:54:02","modified_gmt":"2020-06-02T17:54:02","slug":"php-password-storage-in-mariadb","status":"publish","type":"post","link":"https:\/\/www.wellgolly.com\/?p=2946","title":{"rendered":"PHP password storage in MariaDB"},"content":{"rendered":"<p>Years ago I built a site that had login and account creation capability using SHA1 and MySQL. In preparation for a new webiste I loaded the old site into a droplet it still works fine. At the time SHA1 and simple input sanitizing was fine, but since then SHA1 has been cracked and PDO is recommended for sanitizing database values.<\/p>\n<p>The original code looked like this:<br \/>\n<pre><code class=\"preserve-code-formatting\">\n\/\/ Read the data from the form\n$userlogin = htmlspecialchars($_POST[&#039;login&#039;]);\n$password&nbsp;&nbsp;= htmlspecialchars($_POST[&#039;password&#039;];\n\/\/ The hash stored in the database.\n$passwdHash = sha1($Password);\n\n\/\/ Verification\n$userlogin = htmlspecialchars($_POST[&#039;login&#039;]);\n$password&nbsp;&nbsp;= htmlspecialchars$_POST[&#039;password&#039;];\n$passwdHash = sha1($password);\n$sql = &quot;SELECT *\nFROM users\nWHERE username = &#039;$login&#039; &amp;&amp; password = &#039;$passwdHash&#039; &quot;;<\/code><\/pre><\/p>\n<p>Without really thinking about it, I sanitized the password input with htmlspecialchars and in both storing and retrieving the password it didn\u2019t have any impact.<\/p>\n<p>I basically copied the code into my new project and then changed SHA1 to password_hash. That didn\u2019t work because the <i>password_hash<\/i> requires <i>password_verify<\/i> to check the hash when you retrieve it from the database. That worked when I tested the login code by copying and pasting the login info from php_error.log &#8211;> <code class=\"preserve-code-formatting\">error_log(login: $userlogin&nbsp;&nbsp;hash: $hash)<\/code> into the users table. It didn\u2019t work when I created a signup page and entered the data automatically. The reason is that sanitizing the password with htmlspecialchars changes it somehow. This is what I do instead. Note that it doesn\u2019t matter what the user enters in the password field because the hash function transforms it into a 60 character hash so there is no need to sanitize.<\/p>\n<p><pre><code class=\"preserve-code-formatting\">\n\/\/ Read the data from the form\n\/\/ Sanitized passord is used in javascript just for checking that a password was entered\n$Password = htmlspecialchars($_POST[&quot;Password&quot;]); \n$UserLogin = htmlspecialchars($_POST[&quot;UserLogin&quot;]);\n$PasswdHash = password_hash($_POST[&quot;Password&quot;], PASSWORD_DEFAULT);\n\n\/\/ Enter into the database with PDO\n$sql = &quot;INSERT INTO `Database`.`users` (`user_login`, `user_pass`,\n$sql .=&nbsp;&nbsp;&quot;VALUES (:user_login, user_pass, ...\n\n$stmt-&gt;bindParam(&#039;: user_login&#039;, $UserLogin);\n$stmt-&gt;bindParam(&#039;:user_pass&#039;,&nbsp;&nbsp; $PasswdHash);\n...\n\n\/\/ Validate the password. Retrieve by user_login only. \n\/\/ Don\u2019t do anything to the password that was entered by the user.\n\nforeach($result as $row) {\n&nbsp;&nbsp;$user_login&nbsp;&nbsp;= $row[&#039;user_login&#039;];\n&nbsp;&nbsp;$hash = $row[&#039;user_pass&#039;];\n\n&nbsp;&nbsp;if ( password_verify($_POST[&#039;password&#039;], $hash) ) {\n&nbsp;&nbsp;&nbsp;&nbsp;$_SESSION[&#039;userID&#039;]&nbsp;&nbsp;&nbsp;&nbsp;= $row[&#039;ID&#039;];\n&nbsp;&nbsp;&nbsp;&nbsp;$_SESSION[&#039;userName&#039;]&nbsp;&nbsp; = $row[&#039;user_name&#039;];\n&nbsp;&nbsp;&nbsp;&nbsp;$_SESSION[&#039;userDisplayName&#039;] = $row[&#039;display_name&#039;];\n&nbsp;&nbsp;&nbsp;&nbsp;$passwordIsValid = TRUE;\n&nbsp;&nbsp;}<\/code><\/pre><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Years ago I built a site that had login and account creation capability using SHA1 and MySQL. In preparation for a new webiste I loaded the old site into a droplet it still works fine. At the time SHA1 and simple input sanitizing was fine, but since then SHA1 has been cracked and PDO is &hellip; <a href=\"https:\/\/www.wellgolly.com\/?p=2946\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">PHP password storage in MariaDB<\/span><\/a><\/p>\n","protected":false},"author":6,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[34],"tags":[],"class_list":["post-2946","post","type-post","status-publish","format-standard","hentry","category-php"],"_links":{"self":[{"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=\/wp\/v2\/posts\/2946","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2946"}],"version-history":[{"count":4,"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=\/wp\/v2\/posts\/2946\/revisions"}],"predecessor-version":[{"id":2950,"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=\/wp\/v2\/posts\/2946\/revisions\/2950"}],"wp:attachment":[{"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2946"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2946"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wellgolly.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2946"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}