A Beginner’s Tutorial for Understanding and Implementing Password Hashing and Salting

In this article we will discuss about securing user passwords by using hashing and salting on user passwords. We will first discuss about the theory of hashing and salting. We will then try to implement a simple library that can be used to perform hashing and salting.

Background

I have seen many ASP.NET beginners making the mistake of storing the password as plain text in the database. The first question I ask them is why are they not using the ASP.NET Roles and Membership database and API. In most cases using the default Roles and Membership API will fulfill the needs of the application. In some cases the application really needs to have its own tables to save user credentials. All the applications where custom forms authentication is being used are probably storing user credentials in the application database in some application specific schema.

Note: Please refer these two articles to learn more about custom forms authentication:

  1. Understanding and Implementing ASP.NET Custom Forms Authentication[^]
  2. A Beginner’s Tutorial on Custom Forms Authentication in ASP.NET MVC Application[^]

Passwords as Plain Text

For all scenarios where we need to store user credentials in application tables, storing the password in plain text is never a good idea. Anyone who has access to the database can easily get to know the password of all the users. Also, even a small part of application that is prone to SQL injection can reveal the password of all users. So what could be done to prevent this and store the password in a better way?

Storing Encrypted Passwords

Encryption is the process of encoding the message in such a way that even if anyone get hold of the message, he should not be able to interpret anything from it. To encrypt a message we need two things. First we need an encryption algorithm and second we need a key which will be used for encryption.

So if the requirement is not to store the password in plain text then the First thought is to keep the passwords encrypted rather than as plain text. Well this approach is better than storing the passwords in plain text but it still has the some problem. If someone knows the encryption algorithm and the secret key that was used for encryption then he could decrypt the passwords easily.

Hashing – Storing Password Hashes

Hashing is the process of generating a number or a unique string for a larger string message. The hash for every string message should be unique and there is no way the original message can be reproduced from its hash value.

No matter how strong our encryption mechanism is, there is always a possibility of regenerating the original password if the algorithm and the secret key is known. So the even better approach would be to store the password hashes in the table. This way there is no way to regenerate the password from the hash. Whenever the user tries to log in, we will generate the hash for the password using the same hashing algorithm and then compare it with the hash stored in the database to check whether the password is correct or not.

Now this approach is a lot better than storing the password in encrypted form. But this also has few limitations. To understand the limitation let us look at the following example:

User Password Hash
user1 one 1234
user2 two 2345
user3 three 3456
user4 one 1234
user5 two 2345

The above table shows some dummy data where 5 users have chosen there passwords and there corresponding hash values have been generated to store in the database. Now from this table we can clearly see the limitation associated with saving the hashed password. The problem here is that the

The above table shows some dummy data where 5 users have chosen there passwords and there corresponding hash values have been generated to store in the database. Now from this table we can clearly see the limitation associated with saving the hashed password. The problem here is that the user1 and user4 choose the same password and thus their generated password hash is also same. Same is the case with user2 and user5. So if I get hold of these password hashes and I know the password of user1, I actually know the password of all the users whose hash value is same as the hash value of user1’s password.

Now this problem is less severe than the problem associated with the earlier approaches. But could we not device a technique which will store provide us all the benefits of hashing and will also remove the limitations associated with it. The answer to this is salting and hashing.

Salting and Hashing of Passwords

Salting is a technique in which we add a random string to the user entered password and then hash the resulting string. So even if two people have chosen the same password, the salt for them will be different. So there will never be case when the hash for two users will be same even if they choose the same password. Following table will illustrate the concept in more details.

User Password Random Salt Resultant Password String Hash
user1 one 12 one12 1234
user2 two 23 two23 2345
user3 three 34 three34 3456
user4 one 45 one45 4567
user5 two 56 two56 5678

Now if we look at the above table we can see that even though the user1 and user4 has chosen same password their salt value is different and thus the resultant hash value is also different. Now the important thing to note in this approach is that the salt value should always be random and secondly this should also be stored in the database so that it can be used while comparing the user entered password.

Using the code

Now we have seen the theory associated with the password hashing and salting and why is this technique preferred over saving plain text passwords, encrypted passwords or even saving password hashes. Now let us see how we can implement this salting and hashing in in .NET so that it can be used by the applications like ASP.NET or ASP.NET MVC websites during custom forms authentication.

Let us start with the salt creation process. We need to generate a random number, for this we can use RNGCryptoServiceProvider class. This class ensures that the generated number is always random and unique. So let us implement a simple class which will generate a random number using this RNGCryptoServiceProvider.

Now we have a class that will generate the random salt value for us. Let us now create a class that will take care of hashing a message. We will use SHA256CryptoServiceProvider class to generate the hash. There are quite a few algorithms that we can choose from. Let us see how a hash value can be generated for a string message.

Now we have two classes with us:

  1. SaltGenerator: This class’ responsibility is to generate a random and unique salt every time.
  2. HashComputer: This class’ responsibility is to generate the SHA256 hash value for a given string message.

Now let us look at the salting and hashing process in form of algorithm.

User creation process: 

  1. User enters a password.
  2. A random salt value is generated for the user.
  3. The salt value is added to the password and a final string is generated.
  4. The hash for the final string is calculated.
  5. The hash and the salt is stored in the database for this user.

User tries to log in: 

  1. User enters his user ID.
  2. The user is used to retrieve the users password hash and salt stored in the database.
  3. The user enters his password.
  4. The retrieved salt is added to this password and a final string is generated.
  5. The hash for the final string is calculated.
  6. This calculated hash is compared with the hash value retrieved from the database.
  7. If it matches the password is correct otherwise not.

So let us create a facade class on top of these two classes which will do the major portion of these activities. it will take the users’ id and password and then will take care of doing the rest. It will return the hash and salt to the user. In case of password retrieval, it will ask the user its password and salt and then checks if it matches or not.

Now we have a simple class library ready which is capable of salting and hashing the user passwords. using this library and saving the values in the database will be the applications responsibility. The class diagram of this class library looks like:

salting

Note: The Utility class contains 2 simple methods to convert string to byte[] and vice-verse.

Creating a Test Application

Let us now go ahead a create a simple test application to test this library. Let us create a simple console application. Let us first create a Model class that will hold the user login data.

Note: This is a very rudimentary model for User login details. It is created only to explain the concepts of the article. Real world application will contain more detailed model.

This model class represent a user details for any user from the user login details table. We will use this model while creating a new user and while the user tries to log in.

Now let us try to simulate/mock the database functionality. let us create a simple repository class which will keep all the data in memory rather than pushing them to the database. The real repository class should push the data into the database in the respective operations.

And finally let us write some code to simulate and test the user creation and password comparison functionality.

Let us now try to create a user and then enter a valid password:

successScr

And let us now try to check with wrong password once:

failureScr

And so we have seen the basics of password salting and hashing and have created a simple reusable class library that can be used to create achieve this.

Point of interest

In this article we have discussed the recommended way to saving the user passwords by using salting and hashing on user passwords. We have created a simple reusable class library that can be used to generate the salt and hashes user passwords. I really recommend using this technique whenever we are using custom forms authentication.

This article has been written from a beginner’s perspective. I Hope this has been informative.

Download sample code for this article: HashAndSaltSample