When to use MD5 ?

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

User avatar
nielsene
DevNet Resident
Posts: 1834
Joined: Fri Aug 16, 2002 8:57 am
Location: Watertown, MA

Post by nielsene »

Hmm I wouldn't really call this "high security." Most of what I mention probably falls under the category of "best-practices" or at least as far as I understand them.

Sites I've designed/co-authored:
  • a simple caption contest for photos (users upload photo, other users provide possible captions for the photos, users vote for their favorite n photos)
  • a library system (track cd/video/books checkout/queues, allow user submission of new items, but kept seperate from official library items, allow user rating and commenting of items at the cd or track level)
  • on-line registration site for ballroom dance competitions
The first two use very minimal security, but the library will get this system when I get back to it. The on-line registration system (one module of a larger system I'm working on) currently uses no authentication for some tasks and this "high-level" stuff for any admin-esque functions.

I've also worked on a sourceforge.net offsite install that required additional security code added to it. This site of course uses most of what I've mentioned but also involves specially crafted firewalls, IP/DNS filtering, LDAP, etc. We're hoping to move it to a proper PKI system in the near future with both client/server certs.

So most of my sites are not high visibiity/ likely targets for hackers, but why make things easy for them. I guess its also a bit of "How would I want my account on a remote server protected?" If I expect a certain level of security/privacy from a service, I should make sure my services offer the same amount.

If you only use logins for basically forum post author tracking, then you're probably fine doing the basic level of security. If your website offers some larger service, even just as large as allowing people to edit their old posts for instance, a higher level is probably warranted to minimize the chance of a compromise and to limit the effects of a compromise.

The example I gave is only about a line or two more than the regular basic MD5 login system and protects your users much better. If you code it into your own persoanl library you don't have to worry about it again, so where's the harm in being paranoid.(all security people should be paranoid.) A good site should protect both itself from malicious users and its regular users/community from the bad guys. Most people focus only on the first half.

Another part of the answer is ever since I took a class from Ron Rivest (the R of RSA), I've always wanted to find that one more way of making something more secure. Sure, sometimes I decide its not worth the effort, but its a fun mind game and some of the most intellectually stimulating work I've done.
User avatar
nielsene
DevNet Resident
Posts: 1834
Joined: Fri Aug 16, 2002 8:57 am
Location: Watertown, MA

Post by nielsene »

Here's some sample code to show what the concerns are with using different hash methods:

Code: Select all

<?php

function getMD5Salt()
&#123;
    return '$1$' . substr(MD5(microtime() . getmypid()),0,12);
&#125;

$shortPass1 = "Bob";
$shortPass2 = "Bob1";
$shortPass3 = "Bob1";
$longPass1  = "LongerThanEightCharacters";
$longPass2  = "LongerThanEightCharacters1";
$longPass3  = "LongerThanEightCharacters1";

echo "MD5'd shortPass1: ". MD5($shortPass1) . "<br />";
echo "MD5'd shortPass2: ". MD5($shortPass2) . "<br />";
echo "MD5'd shortPass3: ". MD5($shortPass3) . "<br /><br />";
echo "crypt'd shortPass1: ". crypt($shortPass1) . "<br />";
echo "crypt'd shortPass2: ". crypt($shortPass2) . "<br />";
echo "crypt'd shortPass3: ". crypt($shortPass3) . "<br /><br />";
echo "md5crypt'd shortPass1: ". crypt($shortPass1,getMD5Salt()) . "<br />";
echo "md5crypt'd shortPass2: ". crypt($shortPass2,getMD5Salt()) . "<br />";
echo "md5crypt'd shortPass3: ". crypt($shortPass3,getMD5Salt()) . "<br /><br />";

echo "MD5'd longPass1: ". MD5($longPass1) . "<br />";
echo "MD5'd longPass2: ". MD5($longPass2) . "<br />";
echo "MD5'd longPass3: ". MD5($longPass3) . "<br /><br />";
echo "crypt'd longPass1: ". crypt($longPass1) . "<br />";
echo "crypt'd longPass2: ". crypt($longPass2) . "<br />";
echo "crypt'd longPass3: ". crypt($longPass3) . "<br /><br />";
echo "md5crypt'd longPass1: ". crypt($longPass1,getMD5Salt()) . "<br />";
echo "md5crypt'd longPass2: ". crypt($longPass2,getMD5Salt()) . "<br />";
echo "md5crypt'd longPass3: ". crypt($longPass3,getMD5Salt()) . "<br /><br />";
?>
Sample Output:

Code: Select all

MD5'd shortPass1: 2fc1c0beb992cd7096975cfebf9d5c3b
MD5'd shortPass2: 7f6db5daba8166fe8db919aa13e3dd9b
MD5'd shortPass3: 7f6db5daba8166fe8db919aa13e3dd9b

Crypted shortPass1: NWAVHsP35k2bk
Crypted shortPass2: NWQGr5qAj7gxY
Crypted shortPass3: NWQGr5qAj7gxY

MD5Crypted shortPass1: $1$4c437779$MJdGX.EbpBraXwfwJF/rt0
MD5Crypted shortPass2: $1$48675cd3$8pVcOx41y4K8.4Q7Wlqff/
MD5Crypted shortPass3: $1$f34fb07f$0xuIKlmpml5lM3SvuJE/s1

MD5'd longPass1: 2fec8bc9261ae801e4581a10ecca16c6
MD5'd longPass2: 4f03ac90570dfbb5fa730abd2bd37a55
MD5'd longPass3: 4f03ac90570dfbb5fa730abd2bd37a55

Crypted longPass1: NWuxthO2s1.lo
Crypted longPass2: NWuxthO2s1.lo
Crypted longPass3: NWuxthO2s1.lo

MD5Crypted longPass1: $1$79f71304$Pexmy75lzoweyauP6JzNW1
MD5Crypted longPass2: $1$883eda25$SMJrnElvOmudFr.KxxgDk1
MD5Crypted longPass3: $1$4f648815$.ImxN9i2491c2jCOb2AYc0
If you look at the output (or run the program yourself) you see that MD5 hashes match for shortPass2&3 and longPass2&3 (as you would expect since they are the same input password). Crypt shows the same behavoir (its supposed to provide a random salt for use in 3DES, but looks like it isn't), plus crypt has the added problem of throwing away information in 3DES mode so that all the longPasses hash to the same result. You could write a get3DES salt to give it a nice random two character salt, but the length problem will still exist (crypt($longPass3,$storedLongPass1) will equal $storedLongPass1).

All the md5crypted passwords are unique, even when you give the same password. The above length problem has been fixed.

If you run the program and the crypt output lines also start with '$1$' that's because on your system crypt defaults to MD5 and not 3DES. I beleive *BSD (and Mac OS X) are such systems. I beleive Windows defaults to 3DES as does the Linux machine I regularly use.
Post Reply