Press "Enter" to skip to content

C# code to store uniquely-salted, hashed passwords in the database and validate at login

Last updated on April 3, 2013

For the web application I’m building, I want to keep the users’ data as secure as [reasonably] possible.  One way I’m doing that is by storing the password as a hashed value, with each account having a unique salt value for the hash.  This is useful to prevent rainbow table attacks – a common security issue for passwords stored as one-way hashed values.

Here’s the C# code I’m using to store a hashed password in the database, unique a unique salt value for each account.

For this project, the user’s account name is their email address.

User table structure (MS SQL Server 2008)

IDuniqueidentifiernot null
EmailAddressvarchar(250)not null
Saltvarbinary(250)not null
Passwordbinary(16)not null



using System;
using System.Data;
using System.Linq;
using System.Security.Cryptography;
using System.Web.Security;
using Resources;
namespace DataAccessors
    public class AccountAccessor : BaseAccessor, IAccountAccessor
        public void CreateNewAccount(AccountManagementView userAccount)
                throw new DuplicateRecordException(Literals.AnAccountForThisEmailAddressAlreadyExists, userAccount.EmailAddress);
            byte[] salt = System.Text.Encoding.UTF8.GetBytes(Membership.GeneratePassword(100, 20));
            byte[] hashedPassword = CreateSaltedHashedPassword(salt, userAccount.Password);
                .SetColumnToValue("ID", Guid.NewGuid())
                .SetColumnToValue("EmailAddress", userAccount.EmailAddress)
                .SetColumnToValue("Salt", salt)
                .SetColumnToValue("Password", hashedPassword)
        public bool UserAccountIsValid(AccountManagementView userAccount)
            DataSet results =
                    .Where("EmailAddress", SQLHydra.Enums.Comparators.EqualTo, userAccount.EmailAddress)
            if(results.Tables[0].Rows.Count == 1)
                byte[] salt = (byte[])results.Tables[0].Rows[0]["Salt"];
                byte[] hashedEnteredPassword = CreateSaltedHashedPassword(salt, userAccount.Password);
                byte[] hashedStoredPassword = (byte[])results.Tables[0].Rows[0]["Password"];
                return !hashedEnteredPassword.Where((t, i) => hashedStoredPassword[i] != t).Any();
            return false;
        private static byte[] CreateSaltedHashedPassword(byte[] salt, string password)
            return new HMACMD5(salt).ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
        private static bool AccountForThisEmailAddressExists(string emailAddress)
            int accountsForThisEmailAddress =
                (int) BuildSelectQueryForTable("User")
                          .Where("EmailAddress", SQLHydra.Enums.Comparators.EqualTo, emailAddress)
            return (accountsForThisEmailAddress > 0);

What’s going on in the code

I’m using the GeneratePassword method from .Net’s Membership class.  You want to use a method like this that is cryptographically strong.  Don’t use a random GUID, or something generated from the Random class (which is not truly random).


I’m using MD5 as the hashing method.  There are more secure methods.  However, MD5 is slower than most of the more secure methods.  Therefore, this makes it significantly slower for anyone running a brute force attack.  It’s a trade-off.

If you want to use a more secure hash method, you may need to make the password column’s length longer (e.g., SHA256 produces a 256-bit result).

By using a one-way hash, you don’t have a way to send a user their password, if they forget it.

The best way to handle forgotten passwords is to send the user an e-mail with a link to a page that will only be active for a certain length of time.  They go to that page and enter in a new password, which you then hash and store.

Additional information

To see why you want to use a method like this, read this article

One Comment

  1. Scott
    Scott March 21, 2013

    I cleaned up the code a bit, putting the salted hash creation into its own method (CreateSaltedHashedPassword), since it is used in multiple places.

Leave a Reply

Your email address will not be published. Required fields are marked *