I seen this question Encrypting/Hashing plain text passwords in database
and i am aware i shouldnt do md5("salt" + password); and i see an implementation in python for a solution.
Is there a .NET built in function with params i can use instead of writing my own?
I don't think there's a single function but you can do it in a few lines (here using SHA512, but there are other options):
using (var sha = new SHA512CryptoServiceProvider())
{
byte[] hashed = sha.ComputeHash(Encoding.Default.GetBytes(saltedPassword));
string output = Convert.ToBase64String(hashed);
}
Make sure you use one of the Crypto... classes to ensure the more secure algorithm is used.
Yes, .NET Framework 2.0 and up (to and including 4.5 as of now) implements PBKDF2 (also known as RFC2898 and PKCS#5v2) in a class called Rfc2898DeriveBytes. Technically, it implements PBKDF2-HMAC-SHA-1, which while not as good as PBKDF2-HMAC-SHA-512, is still reasonable for password hashing.
PBKDF2 arguments:
- HMAC is not an argument for this class - HMAC-SHA-1 is fixed in this implementation, so you don't have to worry about it.
- Password is the user's password.
- the plaintext is, of course, discarded after hashing.
- Salt is a cryptographically random per-row string of sufficient length (for instance, at least 8 bytes). Every password needs its own random salt so if 300 users all choose "P@$$w0rd" as their password, the hashed results are all different.
- the salt is stored in plaintext form in the database; you need it the next time you're generating the password hash to see if the result is the same.
- Iterations is the number of times you're going to loop. For any desktop or server hardware, start in the tens of thousands and go up until it hurts.
- the number of iterations should also be stored in plaintext in the database, so that it's trivial to change this number later (i.e. make it higher as processing power increases).
- .GetBytes is the output length in, you guessed it, bytes. In this case, you should use 20.
- Reason (advanced discussion): for password hashing, this should never be more than the native hash size, because an attacker will not need to generate more than that (and generating native hash size + 1 bytes takes double the time, since it starts a whole new set of iterations for each native hash size amount in the output length, concatenating the results together - the attacker can safely assume that if the first output matches, it'll all match, and it's 100% certain that if the first block fails, it's not a match). Since this class is limited to SHA-1, the native hash size is 20 bytes. If you use another library that has the option, SHA-256 is 32 bytes, SHA-512 is 64 bytes.
Note that HMACSHA512 versus Rfc2898DeriveBytes for password hash contains some sample .NET code that I have not analyzed in detail, but which may be a useful starting point.