How to implement iterations when hashing passwords?

To securely hash passwords, algorithms such as PBKDF2 do many iterations of a common hash such as SHA1. Are there certain ways that these iterations need to be done to be safe?

``````function generateHash(algorithm, salt, password, iterations) {
iterations = iterations || 1;
try {
for(var i=0; i<iterations; ++i) {
hash = crypto.createHmac(algorithm, salt).update(hash).digest('hex');
}

return algorithm + '\$' + salt + '\$' + iterations + '\$' + hash;
} catch (e) {
throw new Error('Invalid message digest algorithm');
}
}
``````

Is this a safe way to hash the password? I can imagine that if you have an algorithm such as this that does:

``````HMAC(HMAC(HMAC(password)))
``````

then there exists some faster function

``````HMAC3(password)
``````

that gives the same output. Is this the case?

Yes, there are several requirements for an iterative hash function:

• It should not be possible to do any precomputation, such as using rainbow tables.
• The implementation should avoid running into cycles or fixed points in the hash function.
• The implementation should be as fast as possible, because that is what the attacker would use.

Especially on the final point the example code is lacking. The `crypto.createHmac(algorithm, salt)` should really be outside of the loop. Because the attacker hashes many passwords with the same salt, he can even place the `createHmac` call outside of the password loop, e.g:

``````hmac = crypto.createHmac(algorithm, salt)
for(var i=0; i<iterations; ++i) {
hash = hmac.update(hash).digest('hex');
}
...
}
``````

This gives the attacker an advantage when cracking passwords, which would be avoided if the HMAC used the password instead of the salt as the key, as PBKDF2 does.

By implementing the given code in C and doing some optimizations, I managed to get it to be 10 times faster than the original NodeJS implementation. This means that an attacker can crack passwords 10 times faster than you intended, without even using a GPU or FPGA.

So there does exist a function that does a fast version of `HMAC(HMAC(HMAC(password)))`, simply because `HMAC` does much the same work in every iteration.