6

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?

Community
  • 1
  • 1
user257257
  • 218
  • 1
  • 6

4 Answers4

2

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.

John Bowen
  • 24,213
  • 4
  • 58
  • 56
  • 4
    Very bad plan. A hash without a salt is subject to a rainbow table attack. Your use of the crypto classes was good but you must include a salt to make this answer useful. Also, the last line should use `Convert.ToBase64String`, which is as fast as `BitConverter.ToString` and produces a much shorter string (88 bytes vs 192 bytes in this case). If these two problems are corrected this could become the best answer, IMHO. – Ray Burns Jan 23 '10 at 04:33
  • Thank you for the clarification. Yes, obviously the password should be salted before hashing which I was intending here but I see where the confusion came from. I'll update to be more explicit. Thanks for mentioning the Base64String conversion too. – John Bowen Jan 23 '10 at 14:59
  • Please do not use a single pass of any hash function, regardless of how nice a function it is. Use a methodology that is known to be good at password hashing - SCrypt, BCrypt, or PBKDF2 (like .NET's RFC2898DeriveBytes). While SHA-512 is a good cryptographic hash function, even at a serious disadvantage due to 64-bit operations being poor on 2014 vintage GPU's, [oclHashcat](http://hashcat.net/oclhashcat/) on a single PC with 8x AMD R9 290Xstock core clock can still attempt 797 million guesses per second, or 2E15 guesses per month. – Anti-weakpasswords Mar 29 '14 at 01:45
2

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.

Anti-weakpasswords
  • 2,604
  • 20
  • 25
  • Any comments on how is it better/worse than `FormsAuthentication.HashPasswordForStoringInConfigFile`? – Kuba hasn't forgotten Monica Feb 25 '14 at 03:38
  • 1
    RFC2898 is far better, even with a moronic iteration count of 1 - and tens of thousands of times better with a reasonable iteration count in the tens of thousands! They start with Microsoft's own [Note: This API is now obsolete.](http://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.hashpasswordforstoringinconfigfile(v=vs.110).aspx) and continue through "It's just (almost certainly) unsalted MD5 or SHA-1! Don't do that!!!" based on [Drop in replacement for FormsAuthentication.HashPasswordForStoringInConfigFile?](https://stackoverflow.com/q/13527277/1967612) – Anti-weakpasswords Feb 25 '14 at 03:44
1

No you should not use MD5 for password hashing!!!!!

Bad!!!!! Nor should you perform a salt+password over a single Hash pass (md5 or other)!!! Bad!!!!

Nor should you do salt+password hashed multiple times (unles XOR each hash pass as per PBKDF2!!! Bad!!!!

Use this API: https://sourceforge.net/projects/pwdtknet Good!!!!!

thashiznets
  • 433
  • 4
  • 6
1

Check out FormsAuthentication.HashPasswordForStoringInConfigFile

string hashMD5 = FormsAuthentication.HashPasswordForStoringInConfigFile(Pass + Salt, "MD5");

string hashSHA1 = FormsAuthentication.HashPasswordForStoringInConfigFile(Pass + Salt, "SHA1");
Omar
  • 39,496
  • 45
  • 145
  • 213