I recently did a small topic on md5 salts in my latest project, the
Danish podcast Tech3. The other presenters
got me thinking: Is it really necessary for ordinary people to add
salts to their MD5 hashes?
Well, is it?
Yes.
At least that’s my opinion. Lets take a very simple example here: I,
for some reason or the other, got the hands on a very simple dataset:
username=darthvader&passwd=7d9b53f484b070d715252daf0a3f334b
Wauw - that looks all secure and protected. There is no way I am going
to know what password our dear Darth Vader used to protect his user
account, is there?
Well, let’s do a real life demonstration.
So yes - Darth Vader should have chosen a better password. But really,
deathstar isn’t that bad compared to many ordinary users password.
So, what can we learn from this? That Darth Vader has a very
narrow field of interest? That we shouldn’t use MD5?
In the same order: Yes and No.
By all means - continue using MD5. But this is the trick: Salt it.
And if you have no idea what salting your hash is, this is the short
version: Add a string of text that you know, but nobody else does in
the beginning or end of the string before hashing it.
So, instead of doing
$passwd = md5($userSuppliedPassword);
Use
$password = md5("MySalt_" . $userSuppliedPassword);
Do this every time you need to find the hash for a users password, both
setting and getting it. And the end result: Darth Vader’s hash ends up
being 721797113d36f5604089ed8f90b82ea9 instead.
And this hash isn’t in the rainbow table. And if you had (as you should)
used a better salt it shouldn’t be in any rainbow table.
A simple solution would be to define a constant in some file - preferably
outside your webroot - and pre- or append this constant to the user
supplied password at every check. Or if you feel like you are going to
forget to do this, create your own MD5-wrapper function that auto adds
the constant.
Well, the methods above pretty much all require that they be implemented
prior to any users signing up and their password being stored. But we
all know that most user-databases are carried over from older setups.
So how do we add the salt without knowing the users password.
Well - I can come up with two methods:
Add a second field to the database where you will add the salted hash
after their first login since the addition. This way all users will
eventually have had the new hash set, and you can change over to
using it.
Double-hash your password with your hash in the middle. A rough
example is md5("MySalt_" . md5($userSuppliedPassword)). This is
pretty much the same as before, but you can add this new hash to
existing hashes. The drawback is that you now have to calculate the
hash twice.
So, which one of these is the best? The first one is obviously the hardest
one to do, and will also require more resources in the near future. But
it does have a certain touch as it will eventually have the correct format.
Where as the format that options number two provides just smells of “I did
this poorly first time around, this is my have to make it better”. And we
don’t like that.
So - if you don’t mind smelly pseudo-hacks, go for options number two. It is
by far the easiest and quickest to implement. I would go for option
number one as it will, eventually, produce the best end result. Darth Vader
should tackle his most important problem first and come up with a replacement
for his poor choice of password. Then he should chose which salting option
suits him best. A good salting doesn’t turn bad passwords good.
No. No. And if you still think you should, then no. It is way more important
that you understand why than how. And if nothing else, you should know how.
And having the code brought to you on a silver platter gives you neither.
I hope that this post has spurred a few thoughts in you mind about why you
should care about salting your MD5-hashed passwords. And if you know why
the last part - the how - should come easily. I have given some examples that
should point you in the right direction.
And if you haven’t thought about anything but my silly Star Wars references,
then you’ve missed an important point. But you’ll live. Especially since we
are now able to easily figure out Darth Vaders passwords as he forgot to salt
his hash.
-fangel
October 12th, 2007 | PHP
*linked to perenially beta homepage; brownie points for authenticity?*
You know, if everybody had your life philosophy …
… we’d all be better off.
Kudos for these two snippets:
“The first one is obviously the hardest one to do, and will also require more resources in the near future. But it does have a certain touch as it will eventually have the correct format.”
Gawwwwwd bless you.
“No. No. And if you still think you should, then no. It is way more important that you understand why than how.”
Ooooh, empowering us as though we can each of us be mature adults … citizens, evuhn.
IMNSHO this is the finest kind of geek stuff. A great antidote to the “60% satisfaction is good enough” movement.
keep on keepin’ on!
–bentrem
Comment by Jim Whimpey
Hahaha! Great post, I’m definitely going to do this from now on.
October 12, 2007, 8:58 pm