This question already has an answer here:

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);

marked as duplicate by AviD Oct 16 '13 at 12:21

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new 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.

  • 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. – Ayrx 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... – Ayrx Oct 15 '13 at 6:13

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