What is the easiest way to create and compare a salted password in .NET?

In an ongoing effort to improve my code I am looking for the best way to create and compare a salted password in .NET.

Is there a better, or more secure, way of doing this?

My current code is as follows:

    public static string CreateSaltedPassword(string salt, string password)
    {
        SHA1CryptoServiceProvider SHA1 = null;

        SHA1 = new SHA1CryptoServiceProvider();

        // Convert the string into an array of bytes
        byte[] byteValue = System.Text.Encoding.UTF8.GetBytes(salt + password);

        // Compute the hash value
        byte[] byteHash = SHA1.ComputeHash(byteValue);

        // Dispose the unmanaged cryptographic object 
        SHA1.Clear();

        return Convert.ToBase64String(byteHash);
    }

    public static bool ComparePasswords(string salt, string password, string storedPassword)
    {
        string passwordHash = string.Empty;

        // Create the hashed password
        passwordHash = PasswordProvider.CreateSaltedPassword(
            salt, password);

        // Compare the passwords
        return (string.Compare(storedPassword, passwordHash) == 0);
    }

Answers


You should do a few thousand iterations through the SHA1 hash:

public static string CreateSaltedPassword(string salt, string password, int iter)
{
  SHA1CryptoServiceProvider SHA1 = new SHA1CryptoServiceProvider();
  byte[] byteValue = System.Text.Encoding.UTF8.GetBytes(salt + password);
  do {
    byteValue = SHA1.ComputeHash(byteValue);
  } while (--iter > 0);
  SHA1.Clear();
  return Convert.ToBase64String(byteValue);
}

Do some testing to see how long it takes on your target machine: 1000 to 10000 iterations shouldn't be noticeable to users when you are checking their input, but it will change an attacker's time requirement from hours to years—long enough that the password will have expired before the attacker recovers it.

The salt source and size is not shown; the salt does not need to be secret, it just needs to be unpredictable for a given password. 8 bytes from a cryptographic RNG is a convenient and secure salt. User names are more convenient, but may be a little less secure.

This set up gives reasonable security for most applications today. The next step up in security would be bcrypt. Where I suggested multiple iterations of the hash function above, bcrypt does more methodically with a very slow key generation process.

You may be interested in my answers to these similar questions:


Need Your Help

Align Android Relative Layout Items w/ Dynamic Size Item in Different Linear Layout

android android-layout android-linearlayout android-relativelayout

I haven't been able to find anything out there on aligning a widget from a RelativeLayout to a widget within a horizontal LinearLayout. Aligning from one layout to another is almost not even menti...

Subsetting data in a loop and write results to a list

r loops plyr subset

I have dataframe containing five variables. Two of them are metric measurements and three of them contain groups stored as factors. I try to subset this dataframe three times in a loop by the diffe...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.