Understanding the Difference Between MD5 and Crypt Functions
If you’re working with a user-management system in PHP (or any scripting language), than you’re likely using either the md5() or crypt() function to encode and store the user’s password.
An oft-asked question – and oft-misunderstood – is what is the difference? Is one better than the other?
First, let’s take a quick look at how each one works.
How MD5 Works
MD5 creates a “hash” value based on an input string. It uses a one-way algorithm to turn the password into an unintelligible garble of words. Here’s a sample usage.
echo md5("Bananas");
Output: 1ee31b77d0697c36914b99d1428f7f32
This long string (32 characters) is the md5 hash value of “Bananas.” You can now store it in the database, and when a user wants to log in you compare md5($passwordInput) to this hash value.
Using Crypt to Encrypt a Password
Crypt has very similar functionality, but with a unique twist.
Crypt still encrypts a phrase in a one-way algorithm to create a garbled bunch of characters. Here’s an example…
echo crypt("Bananas");
Output: $1$upPJosTV$HC4n2bUsQFZk2IDN1CLdg.
What’s unique about the crypt() function is that it uses an encryption key (or “salt”) to vary the encryption process. This means that you can encrypt the same password (“Bananas”) multiple times and get different hash values to store in your database.
Do I Have to Store the Encryption Key or Salt?
This is where the crypt() function gets a bit confusing. No, you don’t… because the encryption key is stored in the password itself.
Take another look at this output.
$1$upPJosTV$HC4n2bUsQFZk2IDN1CLdg.
The bold bit of text ($1$upPJosTV$) is the stored salt or encryption key (read how to use crypt() for more information on how this salt is created).
So, no. You don’t have to store the salt anywhere, because it’s stored in the hash’ed text. You can simply use that as the salt in the future to check if the password is correct. Like this…
if (crypt($passwordInput, $hashedPassword) == $hashedPassword) { // Ok, log in and stuff. }
Wait… My Encryption Key Is Stored IN the Password?!?
This is where most people think that crypt() is a waste of time. If the great thing about crypt() is that it uses a customizable encryption key, then isn’t it self-defeating to include the encryption key in the stored password?
Not entirely.
The problem with md5() is that everyone knows the encryption algorithm. Sure, you can’t go backwards… but you can easily build a dictionary of known passwords and known hashes. By storing these in a database, it is feasible to do a simple dictionary check to see if you have a password that goes with a known hash.
Why You Should Use Crypt() Instead
Since each crypt() call can use a unique encryption key, there can be no stored dictionary of password hashes.
Here’s an example. Try running this script to see how different salts or encryption keys can change the output of a crypt() call.
echo crypt("Bananas", 'ab') . '<br />'; echo crypt("Bananas", 'ed') . '<br />'; echo crypt("Bananas", 'pz') . '<br />'; echo crypt("Bananas", 'qp') . '<br />';
Output: abBGdAR.aTnBE edHaZeqWhmLpw pzqz3tbQxuuRI qp/4Jsj38Cq0Y
This illustrates the strength of crypt(). By using a different encryption key, the same password (“Bananas”) can be turned into many different hashes. You can’t simply create a lookup table with known passwords and known hashes – because the hash changes based on the encryption key.
The bottom line is that crypt() doesn’t make your passwords unbreakable or protect them from brute force attacks. If someone wants to take the time to check every possible permutation of characters to get to your password, they can do it.
But crypt() does prevent the use of a password dictionary that contains known passwords and known hashes. This would be a far more efficient way to hack a password than a simple brute force attack. So by using crypt() you’re getting an extra layer of security.
[Note: This article assumes you are using an md5 hash as the salt for crypt(). You could use an extended DES salt or a Blowfish salt for slightly different functionality, but these are not supported on all servers - including mine.]
Tags: encryption, password, php, Security, user
php talk » How to Encrypt and Hash Passwords in Php said this on December 1st, 2009 at 4:06 pm
[...] A dictionary like this would make a hacking attempt much easier than if the computer had to physically hash and check each possible phrase. Here’s some more reading on the difference between md5 and crypt. [...]