I am just wondering what all the security experts think of my method for password hashing. I want to come up with a method I can use for all my future web development projects.

First I create a random salt based on a 32 byte array :

RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider();
byte[] randomNumber = new byte[32];
string salt = System.Text.Encoding.UTF8.GetString(randomNumber);

I would then store that salt in the user's database row.

To hash the password, I would use :

// Create a new instance of the RijndaelManaged
// class. This generates a new key and initialization
// vector (IV).
using (RijndaelManaged myRijndael = new RijndaelManaged())
// Encrypt the string to an array of bytes.
byte[] encrypted = EncryptStringToBytes(salt + password, myRijndael.Key, myRijndael.IV);
string encryptedPassword = System.Text.Encoding.UTF8.GetString(encrypted);

The EncryptStringToBytes and DecryptStringFromBytes methods can be seen here : http://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndaelmanaged.aspx

If anyone could look this over and let me know of any vulnerabilities or places where I could strengthen it, I would greatly appreciate it! Thanks!


I've implemented a version of BCrypt here :

        string myPassword = "password";

        string mySalt = BCrypt.GenerateSalt();

        string myHash = BCrypt.HashPassword(myPassword, mySalt);
| improve this question | | | | |
  • 1
    1) You're using UTF-8 encoding on binary data. Thanks to unfortunate defaults in .net, that means they get corrupted silently. Use Base64 instead. 2) When you use UTF8Encoding, create your own instance, with throw-on-error enabled. That way you don't run into silent corruption. 3) I don't see any hash in your code 4) 32 bytes is overkill. Id use 16. – CodesInChaos Oct 14 '13 at 9:31
  • Besides the mistakes others have pointed out: There is never a most secure way to hash something. You can always add a longer salt or a hash algorithm with a longer key length to increase the exponent of the time it takes to brute-force. At one point you have reached a method which is sufficiently secure, but there is no theoretical upper limit. – Philipp Oct 14 '13 at 15:17

No, no, no, no, no. Encryption is not hashing.

You need to use a strong hashing algorithm like bcrypt or pbkdf2 instead. You can use a library like Bcrypt.Net.

With the library, hashing a password is simply a matter of calling,

BCrypt.Net.BCrypt.HashPassword(password, workFactor);

Verification is just as easy,

BCrypt.Net.BCrypt.Verify(password, hashed_password);

If you do not want an additional dependency in your project, look into using the built in Rfc2898DeriveBytes class instead.

| improve this answer | | | | |
  • Ah, thank you. For the Rfc2898DeriveBytes, how many iterations would you recommend? - Also, do you think my salt creation method is substantial in creating a 32 byte salt? – Chrisgozd Oct 14 '13 at 2:59
  • @Chrisgozd Yes, RNGCryptoServiceProvider is a cryptographically secure RNG so you should be find there. With regards to iteration count, that depends on the hardware you are targeting. The correct answer will be as high as possible without introducing large delays for your users. So, profile profile profile. – user10211 Oct 14 '13 at 3:02
  • Thanks, would you mind checking out my BCrypt edit up above? Thanks! – Chrisgozd Oct 14 '13 at 12:42
  • @Chrisgozd today you usually use 100'000 to 250'000 iterations for PBKDF2. – dom0 Oct 14 '13 at 17:29
  • @Chrisgozd What exactly is BcryptDude? I hope you are just wrapping the Bcrypt.NET library in your own namespace and not rolling your own version of the algorithm... – user10211 Oct 15 '13 at 6:13

Not the answer you're looking for? Browse other questions tagged or ask your own question.