Is there any advantage to
sha1(sha1(sha1($password. $salt)));
Basically having multiple sha1 verses just one sha1
sha1($password. $salt);
Is there any advantage to
sha1(sha1(sha1($password. $salt)));
Basically having multiple sha1 verses just one sha1
sha1($password. $salt);
Do not, I repeat, DO NOT attempt to make your password hash safer by doing "special" things do your hash.
First of all, sha1(sha1(sha1($input)))
only has for side effect to increase the chance of collision* on each iteration. Increasing the chance of collisions is a very bad thing.
Instead of trying your hand at do-it-yourself cryptology, why not trust libraries made by actual experts in the field? Use the Portable PHP password hashing framework.
PHPass actually uses bcrypt, which is an algorithm designed to prevent rainbow table, dictionary and brute force attacks. You can initialize it with a number of rounds: the higher the rounds, the longer it takes to compute the hash. That way, you can create stronger hashes if processing power increases.
* The first call to sha1()
takes infinite input and creates one out of 2
160
outputs. The second iteration takes 2
160
inputs and creates one out of x
outputs, where x <= 2
160
. The third iteration takes x
input and creates one out of y
outputs, where y <= x <= 2
160
.
Why does each call to sha1()
reduces the amount of possible outputs? Because the algorithm behind sha1()
was not designed for one-to-one matching of the hashes. Theoretically, you are bound to have collisions if you were to hash every possible hash.
Yes, this is called key strengthening (but is normally done thousands of times) and the salt should be appended on every iteration for better entropy:
$hash = sha1($password . $salt);
for ($i = 1; $i <= 65000; ++$i)
{
$hash = sha1($hash . $salt);
}
Also, read this awesome blog post - or at least this short quote:
The better you can optimize your password hash function, the faster your password hash function gets, the weaker your scheme is. MD5 and SHA1, even conventional block ciphers like DES, are designed to be fast. MD5, SHA1, and DES are weak password hashes. On modern CPUs, raw crypto building blocks like DES and MD5 can be bitsliced, vectorized, and parallelized to make password searches lightning fast. Game-over FPGA implementations cost only hundreds of dollars.
Using raw hash functions to authenticate passwords is as naive as using unsalted hash functions. Don’t.
What is the state of the art here?
First, what your operating system already gives you: a password scheme “optimized” to be computationally expensive. The most famous of these is PHK’s FreeBSD MD5 scheme.
The difference between PHK’s scheme and the one you were about to use for your social shopping cart 2.0 application is simple. You were just going to run MD5 on a salt and a password and store the hash. PHK runs MD5 for thousands of iterations. That’s called “stretching”.
The short answer is no. When you chain two hash algorithms, all you're doing is creating another hash algorithm that has unknown properties (security-wise). Use a salt (or even better, HMAC).
The more times it has to go through the hashing process, the longer it takes to hash, and the fewer attempts an attacker will get per day. If hashing it once takes 10ms, and hashing it a ten times takes 100ms, then an attacker can attempt 6000 passwords per minute with hashing it once, and 600 per minute with hashing it ten times. Of course, with a web application, trying to brute force at either 6000 or 600 per minute is essentially a DOS attack. Cryptographic hashes tend to take a while to do for this purpose, and it's also common to hash multiple times.
You should probably use sha512 instead of sha1, which you can do with hash()
like hash('sha512',$stringtobehashed);
, sha512 also takes approximately 5 times longer than sha1 to hash.