<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ElbertF &#187; passwords</title>
	<atom:link href="http://elbertf.com/tag/passwords/feed/" rel="self" type="application/rss+xml" />
	<link>http://elbertf.com</link>
	<description>Insights and Updates from a Tech Geek</description>
	<lastBuildDate>Thu, 02 Feb 2012 01:22:22 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>How to store passwords safely with PHP and MySQL</title>
		<link>http://elbertf.com/2010/01/store-passwords-safely-with-php-and-mysql/</link>
		<comments>http://elbertf.com/2010/01/store-passwords-safely-with-php-and-mysql/#comments</comments>
		<pubDate>Sun, 31 Jan 2010 08:43:27 +0000</pubDate>
		<dc:creator>ElbertF</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[passwords]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://ElbertF.com/?p=447</guid>
		<description><![CDATA[First, let me tell you how not to store passwords and&#160;why. Do not store password as plain&#160;text This should be obvious. If someone gains access to your database then all user accounts are compromised. And not only that, people tend to use the same password on different sites so those accounts will be compromised as [...]]]></description>
			<content:encoded><![CDATA[<p>First, let me tell you how <strong>not</strong> to store passwords and&nbsp;why.</p>
<h4>Do not store password as plain&nbsp;text</h4>
<p>This should be obvious. If someone gains access to your database then all user accounts are compromised. And not only that, people tend to use the same password on different sites so those accounts will be compromised as well. Your site doesn&#8217;t even need to be hacked; a system administrator could easily browse your&nbsp;database.</p>
<h4>Do not try to invent your own password&nbsp;security</h4>
<p>Chances are that you&#8217;re no security expert. You&#8217;re better off using a solution that has been proven to work instead of coming up with something&nbsp;yourself.</p>
<h4>Do not encrypt&nbsp;passwords</h4>
<p><a href="http://en.wikipedia.org/wiki/Encryption">Encryption</a> may seem like a good idea but the process is reversible. Anyone with access to your code would have no trouble transforming the passwords back to their originals. <a href="http://en.wikipedia.org/wiki/Security_through_obscurity">Security through obscurity</a> is not&nbsp;sufficient!</p>
<p><span id="more-447"></span></p>
<h4>Do not use&nbsp;MD5</h4>
<p>Storing password <a href="http://en.wikipedia.org/wiki/Hash_function">hashes</a> is a step in the right direction. Cryptographic hashing functions like <a href="http://en.wikipedia.org/wiki/MD5">MD5</a> are irreversible which makes it difficult to figure out the original password. To validate a hashed password, simply hash the password again when a user logs in and compare the&nbsp;hashes.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$password</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'swordfish'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$hash</span> <span style="color: #339933;">=</span> <span style="color: #990000;">md5</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$password</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Value: 15b29ffdce66e10527a65bc6d71ad94d</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>Note that this makes it impossible to retrieve a password from the database. If a user forgets his password, simply generate a new&nbsp;one.</p>
<p>So why not MD5? It is quite easy to make a list of millions of hashed passwords (a <a href="http://en.wikipedia.org/wiki/Rainbow_table">rainbow table</a>) and compare the hashes to find the original passwords (the same goes for other hashing functions like&nbsp;<a href="http://en.wikipedia.org/wiki/SHA_hash_functions">SHA-1</a>).</p>
<p>MD5 is also prone to <a href="http://en.wikipedia.org/wiki/Brute_force_attack">brute forcing</a> (trying out all combinations with an automated script) because of <a href="http://en.wikipedia.org/wiki/Collision_resistance">collisions</a>. This means that different passwords can have the same hash, making it even easier to find one that&nbsp;works.</p>
<p>MD5 collision demo:&nbsp;<a href="http://www.mscs.dal.ca/~selinger/md5collision/">mscs.dal.ca/~selinger/md5collision</a></p>
<h4>Do not use a single site-wide&nbsp;salt</h4>
<p>A <a href="http://en.wikipedia.org/wiki/Salt_%28cryptography%29">salt</a> is a string that is hashed together with a password so that most rainbow tables (or <a href="http://en.wikipedia.org/wiki/Dictionary_attack">dictionary attacks</a>) won&#8217;t&nbsp;work.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$password</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'swordfish'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$salt</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'something random'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$hash</span> <span style="color: #339933;">=</span> <span style="color: #990000;">md5</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$salt</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$password</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Value: db4968a3db5f6ed2f60073c747bb4fb5</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>This is better then using just MD5 but someone with access to your code can find the salt a generate a new rainbow&nbsp;table.</p>
<h4>What you should&nbsp;do</h4>
<ul>
<li>Use a cryptographically strong hashing function like SHA-1 or even SHA-256 (see PHP&#8217;s <a href="http://www.php.net/manual/en/function.hash.php">hash()</a>&nbsp;function).</li>
<li>Use a long and random salt for each&nbsp;password.</li>
<li>Use a slow hashing algorithm to make brute force attacks near&nbsp;impossible.</li>
<li>Regenerate the hash every time a users logs&nbsp;in.</li>
</ul>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$username</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Admin'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$password</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'gf45_gdf#4hg'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Create a 256 bit (64 characters) long random salt</span>
<span style="color: #666666; font-style: italic;">// Let's add 'something random' and the username</span>
<span style="color: #666666; font-style: italic;">// to the salt as well for added security</span>
<span style="color: #000088;">$salt</span> <span style="color: #339933;">=</span> <span style="color: #990000;">hash</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sha256'</span><span style="color: #339933;">,</span> <span style="color: #990000;">uniqid</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">mt_rand</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'something random'</span> <span style="color: #339933;">.</span> <span style="color: #990000;">strtolower</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$username</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Prefix the password with the salt</span>
<span style="color: #000088;">$hash</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$salt</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$password</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Hash the salted password a bunch of times</span>
<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #cc66cc;">100000</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">++</span> <span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$hash</span> <span style="color: #339933;">=</span> <span style="color: #990000;">hash</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sha256'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$hash</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Prefix the hash with the salt so we can find it back later</span>
<span style="color: #000088;">$hash</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$salt</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$hash</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">/* Value:
 * e31f453ab964ec17e1e68faacbb64f05bccceb179858b4c482c1b182ff1e440e
 * f1e10feb5b86c6d367e4eb8f90f2cde5648a7db3df8526878f20a77eed00c703
 */</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>In the above example we turned a reasonably strong password into a 128 characters long hash that we can store in a database. The next time the user logs in we can validate the password as&nbsp;follows:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$username</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Admin'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$password</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'gf45_gdf#4hg'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'
    SELECT
        `hash`
    FROM `users`
        WHERE `username` = &quot;'</span> <span style="color: #339933;">.</span> <span style="color: #990000;">mysql_real_escape_string</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$username</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'&quot;
    LIMIT 1
    ;'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$r</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_fetch_assoc</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">mysql_query</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// The first 64 characters of the hash is the salt</span>
<span style="color: #000088;">$salt</span> <span style="color: #339933;">=</span> <span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$r</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'hash'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">64</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$hash</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$salt</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$password</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Hash the password as we did before</span>
<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #cc66cc;">100000</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">++</span> <span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$hash</span> <span style="color: #339933;">=</span> <span style="color: #990000;">hash</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sha256'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$hash</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000088;">$hash</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$salt</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$hash</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$hash</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$r</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'hash'</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// Ok!</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>A few additional tips to prevent user accounts from being&nbsp;hacked:</p>
<ul>
<li>Limit the number of failed login&nbsp;attempts.</li>
<li>Require strong&nbsp;passwords.</li>
<li>Do not limit passwords to a certain length (remember, you&#8217;re only storing a hash so length doesn&#8217;t&nbsp;matter).</li>
<li>Allow special characters in passwords, there is no reason not&nbsp;to.</li>
</ul>
<p>That&#8217;s it, happy&nbsp;coding!</p>
]]></content:encoded>
			<wfw:commentRss>http://elbertf.com/2010/01/store-passwords-safely-with-php-and-mysql/feed/</wfw:commentRss>
		<slash:comments>31</slash:comments>
		</item>
	</channel>
</rss>

