Secure Password Hashing

2019-01-07 19:45发布

I need to store a hash of a single password in a .Net WinForms application.

What's the most secure way to do this?

In particular:

  • Salt, HMAC, or both?
  • How much salt?
  • How many iterations?
  • What encoding? (The password is plain ASCII)

I assume that the algorithm should be either SHA512 or HMACSHA512.

9条回答
你好瞎i
2楼-- · 2019-01-07 20:00

You could follow a published standard, like pkcs#5. see http://en.wikipedia.org/wiki/PKCS for a short description, or http://tools.ietf.org/html/rfc2898 for the RFC.

查看更多
走好不送
3楼-- · 2019-01-07 20:01

I think you should stick with open standards. Among the current hash schemes, the "{ssha}" used by OpenLDAP is very secure and widely used. You can find the description here,

http://www.openldap.org/faq/data/cache/347.html

Most LDAP libraries implement this scheme.

查看更多
ゆ 、 Hurt°
4楼-- · 2019-01-07 20:05

I can recommend BCrypt.net. Very easy to use and you can tune how long it will take to do the hashing, which is awesome!

// Pass a logRounds parameter to GenerateSalt to explicitly specify the
// amount of resources required to check the password. The work factor
// increases exponentially, so each increment is twice as much work. If
// omitted, a default of 10 is used.
string hashed = BCrypt.HashPassword(password, BCrypt.GenerateSalt(12));

// Check the password.
bool matches = BCrypt.CheckPassword(candidate, hashed);
查看更多
放我归山
5楼-- · 2019-01-07 20:06

Hash and Salt. If you only hash you could be attacked by a rainbow attack (reverse has lookup) and a salt makes this much more difficult (random salt would be best.) For your encoding you will probably want to either Base64 or Hex encode your resulting byte array. If you just try to store the byte array as Unicode you could run the risk of some data being lost because not all patterns are valid characters. This also allows for an easier way to compare hashes (just compare the base64 or hex string when you want to validate instead of comparing the byte array)

An increased number of rounds doesn't do much beyond slowing down would be attackers. But is also makes is much more difficult to reuse the hashes in the future if you lose or need to recreate your hash algorithm. You might check out a standard password hash such as crypt on unix systems. This allows for you to change out the hash algorithm and can even support versioning.

But again, a simple hash + salt is good enough for most applications.

查看更多
做个烂人
6楼-- · 2019-01-07 20:08

RNGCryptoServiceProvider to generate a random salt, then SHA512 the password with the salt, and finally store both the password hash and the corresponding salt if you want to later verify that some text equals the stored password.

查看更多
兄弟一词,经得起流年.
7楼-- · 2019-01-07 20:09

Strictly looking at more secure:

Salt, HMAC, or both?

Both would be more secure. Since the key to the HMAC could be considered a salt, doing both would be a little redundant, but still more secure because it would take more work to crack.

How much salt?

Every bit of salt would double the combinations that would need to be maintained in a rainbow-table to easily crack the password. But since there is only one password, and only one salt, more may not be needed. The HMAC uses the block size of the underlying hash for its key size, 1024 bits for SHA512. The block size should be good enough for the salt, but doubling or tripling it would make cracking the password with a rainbow-table much, much harder.

How many iterations?

The more the better. Sure, more iterations means it will take longer to determine if the correct password was entered, but computers are fast and users will not mind waiting for a few seconds while verifying the password. Doing more iterations would mean that someone cracking the password would have to do more iterations too.

What encoding? (The password is plain ASCII)

Might as well encrypt (with AES) the over-iterated, over-salted, HMAC'ed, super-secure password along with its salt just to make it harder. Make the password for the encrypted password hash and key, be some combination of strings that should appear in the executable such as "RNGCryptoServiceProvider" or "System.Security.Cryptography". And while encoding we might as well convert it hex, or base64, or better yet base-36 or some other less expected conversion.

Note: This was mostly written in jest, but should still contain some truth.

查看更多
登录 后发表回答