Wednesday, September 8, 2010

ASP.NET Security: Hashing User Passwords

One of the best security practices concerning any web application that requires user authentication is to encrypt a user's password in the database. However, I take this a step further which is also a best practice, it is a one-way encryption. This means nobody will ever know the user's password, which is how it should be. He/she may be using it somewhere else.

Think about this the next time you go to a website and they have a method of sending you your original password. This is bad. This means either 1) they are not encrypting your password, or 2) it is being encrypted such that it can be decrypted back to its original value. Either way, this is a bad practice.

This is totally unacceptable to me. I won't create an application unless the passwords are encrypted using a one-way hash. If the person loses her password, she will need to be sent a new one in which case the password will need to be changed upon the next logon.

This one-way password hashing is built right into the .NET Framework, so you don't have to go out and buy a product. Upon registration, the user enters in the password and you create a random set of characters, typically called a salt, and then hash the password with the salt and store it in a database. Code snippets are as such:

private static string CreateSalt(int size)
{
//Generate a cryptographic random number.
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] buff = new byte[size];
rng.GetBytes(buff);

// Return a Base64 string representation of the random number.
return Convert.ToBase64String(buff);
}

private static string CreatePasswordHash(string pwd, string salt)
{
string saltAndPwd = String.Concat(pwd, salt);
string hashedPwd =
FormsAuthentication.HashPasswordForStoringInConfigFile(
saltAndPwd, "sha1");

return hashedPwd;
}


Store the PasswordHash and salt in the database in the user's account.

Then, when the user attempts to logon the next time, grab the salt from the database and hash it as usual with the password provided by the user during logon and compare that value to the PasswordHash in the database. If they are the same, the user provided the correct password (whatever that may be). If they are not the same, the password entered was incorrect.

These are common ASP.NET security routines that should be in your own personal library for use over and over again. Keep the database specific details out of the library as the actual database and table schemas may change from project to project. Just pass in variables representing the user supplied username and password and the HashedPassword and Salt in the user database. Build these good security practices once and re-use over and over again.

No comments:

Post a Comment