Blog: Passwords
One-way password hashing is essential, but it’s even better if you select the right algorithm
One-way hashing and salting of passwords is a no-brainer. BUT the choice of hashing algorithm is often overlooked. Some algorithms can make a hash a great deal harder to compute, and therefore protect the password far better.
Start by making the ‘what if’ assumption. Given significant breaches in recent months, one would be wise to consider what would happen if password hashes were stolen. Ideally in this scenario you’d make it as hard as possible for an attacker to recover the plain text passwords from the compromised database of hashes.
Did your developers use a hashing algorithm that is easy and quick to compute, say SHA-1? Was it a requirement in order to make the application meet its performance targets?
SHA-1 based hashing is quick to do, and while it’s easy to check your candidate password for a valid user, it’s also very quick for an attacker to compute hashes in order to unmask the password. You need to make it as expensive in time and processing power as you reasonably can.
If an algorithm takes longer to compute the hash, then you can significantly increase the time it takes for your hashes to be ‘cracked’ in the event of a breach.
A stronger algorithm might cause a user a slight login delay, but it makes cracking MUCH harder.
One example is PBKDF2
(Password-Based Key Derivation Function 2), which is codified in RFC2898. This takes a “salt” which should be a random string, which is stored along with the password, and whose function it is to make it impossible for an attacker to precompute a list of password/hash combinations. In this case, PBKDF adds a salt and a number of “rounds”, or iterations of the algorithm.
So, here is a comparison. First SHA-1, unsalted
NB: Timings are comparative rather than absolute, as the other functions in the request may add time.
$ time echo -n PASSWD | sha1sum
dd6be78993bf6c58f5af3c87dc7467e318c8d5e4
6ms
…quick to process
Then, the standard UNIX md5-based crypt that we all know and love (but should have left behind some time ago, in favour of newer algorithms!)
$1$SALT$yxAWRWyhULxdyPWkIpQPA018ms
…fairly quick to process
Then PBKDF2, salted and with 123,456 iterations
… yes, that’s nearly 75 times slower
In the third example we’ve increased the number of iterations to 123,456 which hugely increases computation requirement, and hence protects the hash a great deal better.
In the first example we’ve got an unsalted SHA1. An attacker *me* can crack that pretty quickly. My laptop’s video card is nothing special, but it’ll go through SHA1 at 6.1 million guesses per second, making it feasible to run through a very large dictionary. (Output redacted for clarity):
C:\oclHashcat-1.01>cudaHashcat64.exe -a 0 -m 100 dd6be78993bf6c58f5af3c87dc7467e318c8d5e4 big-dictionary.txt
Session.Name…: cudaHashcat
Status………: Cracked
Speed.GPU.#1…: 6117.2 kH/s
Then the second example, the older style UNIX md5-based crypt, which uses a salt, but only one round.
C:\oclHashcat-1.01>cudaHashcat64.exe –a 0 -m 500 $1$SALT$yxAWRWyhULxdyPWkIpQPA0 c:\combined.txt
Status………: Cracked
Speed.GPU.#1…: 107.0 kH/s
Which makes things a little harder, but still too easy for a modern attacker. Incidentally, my UNIX password file actually uses “$6$”, or SHA512-based passwords, which I can only crack at something like 2,500 guesses/sec because of the increased number of rounds used.
So, always use salted hashes with an algorithm that requires significant computation to generate an individual hash. Also make sure the salt is generated randomly for each password.
If breached, it will give you and your users more time to react, more time to investigate the breach, more time to get the message out and more time to get their passwords changed.