In response to my previous post…

My last post, Don’t store passwords as plain text! I described a simple method to create a salted hash of a password for a more secure method of storing it in a database.  If you haven’t already done so, you should read that post, to learn WHY its bad to store passwords as plain text (if it isn’t obvious to you). I thought about the topic some more.  It is a very serious security issue, and so I decided that, if I’m going to make a post about the topic, I should be a little more informative.

I also read up a little on the topic.  It turns out that Jeff Atwood posted a pretty similiar post a couple years back.  Jeff made an assertion that I should make as well.  Like Jeff, I am not a cryptographer, so don’t trust my advice like I am a security EXPERT.  He also taught me about rainbow tables.  Rainbow tables, in short, are a massive database of precomputed hashes.  With our hash inside of a hash technique, the final hash product is too long for modern rainbow tables to be effective.  This is great and all, but there are a few problems with my method.  One thing you need to realize when dealing with system security is there will almost ALWAYS be security holes.  We do our best to prevent them, but we can’t promise to be 100% successful.

I’m going to revisit the salted hash to create a better salting, hashing, hacker-hater method of storing passwords.  I’ll make another disclaimer-like notice first.  Most people use only a handful of unique passwords (and by handful, I mean: one.. or two) across a galaxy of login systems.  If you develop a system to store a user’s password it is your responsibility to store it in the most secure way you can.  I don’t recommend you use my salty hash method, I simply mean for it to be an enlightening moment of: “Oh crap, I should really think about how I’m storing my users’ passwords.”  There are always security holes.  I’ve already thought about one in my original.  I thought my method worked well, because the salt wasn’t exposed in the stored value. I liked this, but then realized a problem: two user’s with the same password will generate the same hash.  This is much the problem with storing a non-salted hash, and is the principle used in cracking hashes via brute force/rainbow table.  Hashing strings until the two generated hashes match.

Here is my improved method, in (PHP) code:

// our password this time, is a little bit stronger than ‘password’
$password = “#aBc.123@”;

// some alpha-numeric values and special characters, for use in our salt
$salt_material = “abcdefghijklmnopqrstuvwxyz1234567890 \”!@#$%^&*()_=+-{}[],./<>?;’:”;

// salt will be a string of random length, 1-9
$salt_length = rand(1,9);
$salt = “”;

//build the salt from our material at random choice
for($i = 0; $i < $salt_length; $i++) {
$salt .= $salt_material[ rand(0, strlen($salt_material)-1) ];
}

// calculate the hashes, and then reverse the strings
// not sure about the added strength, but I like the idea of reversing the sums
$salt_sum = strrev( md5($salt) );
$password_sum = strrev( md5($password) );

// now create the sum of our salt + password
$salty_hash = md5( $salt_sum . $password_sum );

// create a hash which exposes our salt, so we know what it was.
// since our salt_length is only 1-9, this information doesn’t have to be
// separated, its always the first char
$resulting_hash = $salt_length . $salt . $salty_hash;

// for added measure, an idea I read elsewhere.
// again, not sure about the added strength, but I like the idea of it
$secure_hash = sha1($resulting_hash);

// and now, the final result
$final_product = $salt_length . $salt . $secure_hash;

Now, each time the hash is calculated, it should be a unique value, however we should be able to recreate it (provided the user inputs the correct password).  Four runs of the script resulted in the following hashes:

7{5@a#@@f77a51b733b65590d284b990099fc764239fbd63
4n+b44c38fe32b4f9a095d7534610bce0f4d72d2976f7
9r{j&f2i”t9ea7035cf81de87a07980e9884d26db67e510728
4;xd”a9ff52b67313cc2d183b977226747a6685540a43

Leave a Reply