Storing weak passwords stronger

PostPosted: Wed Aug 24, 2005 12:18 am Post subject: Reply with quote
We store our passwords in an md5 style password hash that the PHP crypt function provides. It takes a 13 character salt.

My friend and co-worker brought up a good discussion with me. The discussion was what if the database was to be compromised. Could the passwords be cracked? The answer: yes, a dictionary/brute force cracker, like John the Ripper, could be used to crack as many passwords as possible. In a database with over 1 million passwords, a percentage of them are crackable, probably a large percent.

So, the idea of using a different algorithm to store passwords came up. What if we used:

crypt($password.$username.$appname, $salt)
instead of:
crypt($password, $salt)

This way, the theif of the database would have to know something about our password storing algorithm to be able to crack passwords. Even so, John The Ripper isn’t ready to just plug in and go on this algorithm, so even if they did know the way we do it, they would still have more trouble, and surely reduced efficiency in cracking the passwords they have found.

So, it isn’t a surefire method, in that it doesn’t make passwords uncrackable, but it makes it a lot harder.

crypt($password.$username.$appname, $salt)

Hmmm, we’re just postpending some known data onto the end of the password, making it longer. Couple things to consider… the MD5 style password that the PHP crypt function creates will only work on the first 32 characters. This is tremendously better than the traditional 8 characters, but still it’s limited.

We could make the password algorithm much more complicated, like this:

Code:

<?php

function encryptPassword($password, $salt=false)
{
$prepend = ”;
$postpend = ”;
$len = strlen($passsword);
if ($len <= 30)
{
$diff = 32 – $len;
$padding = floor($diff/2);
$prepend = substr(md5($_SESSION[‘username’]), 0, $padding);
$postpend = substr(md5($_SESSION[‘appname’]), 0, $padding);
}
if (!$salt)
$salt = ‘$1$’.substr(md5(uniqid()), 0, 10);
return crypt($prepend.$password.$postpend, $salt);
}

$password = “password”;
$_SESSION[‘username’] = ‘john';
$_SESSION[‘appname’] = ‘test';

// CREATE A PASSWORD:
$encrypted = encryptPassword($password);
print “$password encrypted is: $encrypted\n”;

// the salt used to make the above password was
// random. The first 13 chars are the salt.
// So, to test the password:
$salt = substr($encrypted, 0, 13);

$test = “password”;

if ( encryptPassword($test, $salt) == $encrypted)
print “$test is the correct password\n”;
else
print “$test is not the correct password\n”;

?>

Does this make it more secure? Yes and no. If you know the algorithm, you can definitely write a program or modify John The Ripper, to guess and crack passwords, but this adds another layer of complexity, which may scare away a novice hacker.

One thing that is cool about this is that all the passwords stored in the database are a full 31/ 32 characters. This is good, it will make a brute force attack practically impossible.

Comments are closed.