60
$\begingroup$

Using a cryptographic hash to store e.g. passwords in a database is considered good practice (as opposed to storing them plaintext), but is subject to attacks on said cryptographic hash, assuming the database is compromised.

Which properties of a cryptographic hash function make it suitable for hashing passwords and the like?

Which functions are secure enough, while still being widely available, without patent issues and not too computationally intensive?

$\endgroup$
1

2 Answers 2

64
$\begingroup$

For password-hashing, you should not use a normal cryptographic hash, but something made specially to protect passwords, like bcrypt.

See How to safely store a password for details (this article advocates the use of bcrypt).

The important point is that password crackers don't have to bruteforce the hash output space ($2^{160}$ for SHA-1), but only the password space, which is much much smaller (depending on your password rules – and dictionaries often help). Thus we don't want a fast hash function, but a slow one. So your not too computationally expensive requirement is actually not possible to met. Bcrypt and friends* are designed for this.

*Bcrypt and friends: All slow hash functions. There is PBKDF-2 (which basically just iterates a fast hash with salt some configurable large amount of rounds, and thus the brute force can be easily parallelized - but it is mentioned in a NIST standard, which might be important for certain uses), bcrypt (which additionally needs 4 KB of memory, which makes parallelization (of the brute force) on standard GPUs quite slow, but can be still attacked on custom hardware with 4KB cache per processing unit), and scrypt (which takes not only a configurable amount of time, but also a configurable amount of space to execute (with a possible trade-off to time), and thus brute-forcing can not be easily (cheaply) parallelized).

Of course, you always should use a salted hash (a salt is automatically included in bcrypt). A salt is stored together with the hash in the database (e.g. it is not more secret than the hash), and will be hashed together with the password to produce the hash.

A salt alone does not help against a brute-force attack against specifically your password, but it helps against rainbow table attacks (i.e. attacks with precomputed hash lists), which can attack with the same effort all passwords everywhere at the same time, instead of only all passwords with the same salt (which should be about only one).

There is also the concept of a "secret salt" (also known as pepper), which is not stored together with the password, but at some other location not accessible by a possible attacker. (You would then usually use the pepper, as a non-user-specific piece of information, together with a normal salt.)

This does work only for some attack scenarios, where the attacker does have only (reading) access on the database (or maybe some less secured backup copy on it), but not on this pepper data (i.e. we have an attacker who can't yet execute arbitrary code on the server).

Another possibility would be to use some kind of cryptographic hardware (a token) attached on the server with an embedded key, which does some hashing operation on salt, key and password to produce the hash. Make sure to rate-limit this in case it is stolen, and make sure it does not have an interface to retrieve the secret key, otherwise your attacker (if she succeeds to gain execute access on the server) can use this, too.

$\endgroup$
4
  • 1
    $\begingroup$ It's been a while since I studied parallelization, so maybe this is obvious: how is PBKDF-2 easily paralellizable? If the hash algorithm is cryptographically secure, then it seems it would be impossible (barring some weakness) to paralellize serial iterations. Doing so would require foreknowledge of the output of the hash algorithm. You can't parallelize f(a) = b, f(b) = c, f(c) = d because you can't start f(b) until you've run f(a), ditto for c. $\endgroup$
    – Patrick M
    Mar 19, 2013 at 20:02
  • 1
    $\begingroup$ @PatrickM A single run of PBKDF-2 itself is not parallelizable, but if you are brute-forcing a password, we have lots of runs of the same hash function with different passwords. That can be parallelized to different degrees for the three schemes mentioned. I'll have to look how I can express this clearer in my answer. $\endgroup$ Mar 19, 2013 at 20:11
  • $\begingroup$ Ah, that is much clearer. But I can't think of any brute force attack that isn't parallelizable... botnet to attack a server or if you have the list of hashes, throw more hardware at it and spin up more threads/vms. $\endgroup$
    – Patrick M
    Mar 19, 2013 at 21:39
  • 2
    $\begingroup$ The point is cheaply. PBKDF-2 with a fast hash function (which doesn't use much memory itself) can be implemented on GPUs, and then costs (for each call) a lot less than the original execution by a "normal computer". Bcrypt needs 4K of fast accessible memory, which typical GPUs don't have – so the speed up is limited by the capacity of the memory bus of your GPU. Still, custom hardware can help here. Scrypt needs a lot of memory (when using the right parameters), and memory, while typically available for the "normal user" on a PC, is not cheaply available for a brute force attacker. $\endgroup$ Mar 19, 2013 at 21:52
18
$\begingroup$

More practical questions like this which really turn on the question of risk management are more suited for the broader audience at https://security.stackexchange.com/

I recommend looking at the many password-hashing-related questions there, e.g. How to securely hash passwords.

Bcrypt is recommended there for many situations. But if you need to use algorithms that are approved for US government work you might prefer PBKDF2. Alternately if your main concern is long-term resistance to hardware attacks, scrypt would be more suitable, given how it is "memory-hard" and resistant to hardware attack.

So there is no one true answer, and it is best to go where the experts on risk management gather.

Update: The Password Hashing Competition established the modern baseline for good properties in password hashing algorithms. In 2015, it selected a winner: Argon2. Argon2 was designed to be "memory hard" to make GPU implementations by crackers hard; simple; highly configurable; resistant to side-channel leaks, etc. It seems to be passing the test of time, though as pointed out by Thomas at Are there more modern password hashing methods than bcrypt and scrypt?, we should always be wary of shiny new algorithms.

$\endgroup$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.