Securely hash passwords - so much conflicting advi

2019-02-09 21:01发布

问题:

I'm reading so much conflicting advice as to how to store passwords securely. All I know for sure is not to use MD5! I've seen people advocate using PHP's bcrypt function, which seems like it'd hog the server's processor. I've seen advocates for salts, and advocates for not using salts.

It's all just so unclear. Is there real and credible advice as to how to store passwords securely?

Edit: After a fair amount of research, I found an article from ;login: that deals with the topic in quite some depth: http://www.usenix.org/publications/login/2004-06/pdfs/alexander.pdf

回答1:

Well, there is several parts to this.

  1. You need to try to make it difficult to get to your db and passwords in the first place, keep them secure. This includes not making your passwords cleartext and not using a symmetric encryption algorithm.
  2. You need to use a salt. Doing this prevents people from using a precomputed lookup table (i.e. rainbow table) or something like http://md5.rednoize.com/. Pick some data for your salt that is both unique and unpredictable. I usually use a random 32 bit value, but I wouldn't go much less.
  3. Some algorithms are stronger than others. This is defined in a couple ways
    1. How fast it can be computed. Longer is better. The faster the attacker can calculate hashes, the better the odds are for a bruteforce attack.
    2. If the algorithm has no known weakness which reduce the search space. For example, the number of bits in an md5 hash is misleading because there are known attacks that reduce the actual search space

As of today I think SHA1 or SHA2 with a salt is reasonably secure for the near future. There is a utility called bcrypt which uses an asymmetric variant of blowfish and has the concepts of salt and computational expense built-in, it might be worth checking out.


Edit: I wanted to clarify what a salt is, as there is a lot of misconception about it on SO and online.

What a Salt is not

A secret, pre-agreed upon string that you hash with the password. This is a secret key, not a salt.

What a Salt is

You include the salt (unique and unpredictable per hash) along with your password when hashing, but you also include a unencrypted copy of it outside of your hash, so that when verifying the hash later you are able to include the same salt when given a test password before hashing it so you can properly compare the hash.



回答2:

The point of bycrpt is to hog the processor! (Relatively speaking.) It is for this reason that it is "better" for password hashing than SHA1/2. (This "better" assumes that the password hashes are already in the hands of the attacker or otherwise exposed; while it would nice if it were not the case, even big corporations have had security compromises.)

This requirement was explicitly considered for bcrypt -- if you can only process 1k hashes a second (still, that's a good bit of log-in attempts), how long will that take an attacker to brute-force? A good bit longer than if they could process 10 million hashes a second! The target attack space of a brute-force that is only of the allowed password input, which is often much smaller -- esp. in practice with "simple passwords" -- than the space of the hash!

And a salt is very much required to avoid rainbow tables which trade time for space :) A rainbow table would effectively need to be created for each unique salt value. (Thus, the more unique salt values, the more space is required and with enough values this becomes impractical for an attacker.)

Happy coding.



回答3:

First of all you need to use a good hash function, I suggest SHA-256. You can create a SHA-256 hash like this:

$hash = hash('sha256', $password);

In addition you could also use salting like this:

$salt = 'salt here';
$hash = hash('sha256', $salt . $password);

Moreover, you can use HMACs, like this:

$secret = 'your secret';
$hmac = hash_hmac('sha256', $password, $secret);

The best way to create solid hashes is through salting and iteration. You should loop the above functions until hashing takes 200ms.

You could also go ahead and use encryption, but that would be a bit overkill for most situations.



回答4:

This is similar to this question: Methods for storing login information in database

Credible advice: Never store your passwords in clear text!

Beyond that you have some choices to make. As I mentioned in the response to the linked question, there are two camps: let some else store your authentication data or do it your self. If you decide to do it your self, then you need to come up with a hashing routine. This should probably include a salting your passwords.



回答5:

You can use sha256. A good thing to do is to add extra information to the password such as username, userid, or some other data to it. This way, if someone hack your database, it will be impossible to use an existant hash database to find the password. They will have to crack the password starting from zero.