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 your hash with secure random salt of at least 128bits or longer, to avoid a rainbow attack and use BCrypt, PBKDF2 or scrypt. PBKDF2 comes with NIST approval.
To quote: Archive.org: http://chargen.matasano.com/chargen/2007/9/7/enough-with-the-rainbow-tables-what-you-need-to-know-about-s.html
The problem is that MD5 is fast. So are its modern competitors, like SHA1 and SHA256. Speed is a design goal of a modern secure hash, because hashes are a building block of almost every cryptosystem, and usually get demand-executed on a per-packet or per-message basis.
Speed is exactly what you don’t want in a password hash function.
Fast password validation functions are a problem, cause they can be attacked using brute force. With all the algorithms above you can control the "slowness"
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);
For a server-side implementation with a large number of passwords, you should definitely use a tunable iterated approach like bcrypt. This well-known article on the topic is still (mostly) relevant:
http://www.securityfocus.com/blogs/262
For a single password in a stand-alone application, where the storage location is probably already secured by the system's own authentication system, I think it's much less important. A single strong hash is likely good enough, and adding salt is easy enough that there's no reason not to do so.
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.
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.
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.