How to hash passwords with a salt in .NET

In this post we learnt about using hashing in .NET. We also saw one of its basic functions in the same post which is message verification. In this post we saw how hashing coupled with a random key can be used for message authentication.

We also mentioned another common usage of hashing which is password storage. A password should never be stored as clear text in your system. Instead we save its hash value and when a user enters a password in a login field then we compare the hashed values instead of the plain string passwords. However, a simple one-way hash is generally still not good enough.

The two most common types of attack to guess passwords are the following:

  • Dictionary attack: the attacker goes through a list of words as possible passwords using a dictionary
  • Rainbow table attack: similar to a dictionary attack but in this case the dictionary contains the hashes of various passwords. For each different password a rainbow table can contain its SHA-1, SHA-256, SHA-516 etc. hash. If the attacker finds a matching hash then they have guessed the hashing algorithm and the original password

These databases are generally quite large and can reach several GBs. With software and processing power available today a hacker can test millions of passwords in minutes or even seconds. So it’s not like a determined malicious attacker will test the 10 most popular passwords like “password”, “passw0rd” or “holiday” and then give up. Therefore we need more than just simple hashes to increase security. This is where a password salt enters the picture.


Imagine that you’re trying to cook some tasty soup. You add the basic ingredients to a pot of boiling water such as potatoes, noodles and carrots. If you don’t add anything else then your soup won’t have much taste, right? We need something extra, something that adds more taste such as spices: pepper, salt, paprika and the like. The soup without the spices can be viewed as the hashed password. Pretty much anyone can prepare it, i.e. it’s easy to make. However, if you start adding spices and you have some “secret” combination of them to make your soup extra tasty then it will be much harder for your guests to guess what you’ve put in it an in what quantity. The soup with spices is like a password hashed with a salt.

The concept is simple. We add a random set of bytes to the bytes that represent the password and hash that extended set of bytes instead. In effect our password won’t be “S3cret” but something like “S3cretuy8A7NQlIfNSgRbnGJrBOp6PhLs=” where “uy8A7NQlIfNSgRbnGJrBOp6PhLs=” is the base 64 string representation of the password salt. The user won’t need to know this salt, it is stored along with the hash in the database. Then when we check whether the password is correct then we need to consider the salt as well.

The extended password will be much harder to guess with the techniques mentioned above.

The blog post on hashing and this post about random number generation are enough to build a demo.

Let’s start with a container object to hold the salt and the message digest to be returned from a function:

public class HashWithSaltResult
	public string Salt { get; }
	public string Digest { get; set; }

	public HashWithSaltResult(string salt, string digest)
		Salt = salt;
		Digest = digest;

Here’s is our random number generator class – for details check out the link provided above:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;

namespace RandomNumberGenerator
    public class RNG
		public string GenerateRandomCryptographicKey(int keyLength)
			return Convert.ToBase64String(GenerateRandomCryptographicBytes(keyLength));

		public byte[] GenerateRandomCryptographicBytes(int keyLength)
			RNGCryptoServiceProvider rngCryptoServiceProvider = new RNGCryptoServiceProvider();
			byte[] randomBytes = new byte[keyLength];
			return randomBytes;

…and here comes the password hasher:

using RandomNumberGenerator;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace HashingAlgos
	public class PasswordWithSaltHasher
		public HashWithSaltResult HashWithSalt(string password, int saltLength, HashAlgorithm hashAlgo)
			RNG rng = new RNG();
			byte[] saltBytes = rng.GenerateRandomCryptographicBytes(saltLength);
			byte[] passwordAsBytes = Encoding.UTF8.GetBytes(password);
			List<byte> passwordWithSaltBytes = new List<byte>();
			byte[] digestBytes = hashAlgo.ComputeHash(passwordWithSaltBytes.ToArray());
			return new HashWithSaltResult(Convert.ToBase64String(saltBytes), Convert.ToBase64String(digestBytes));

The function accepts the password to be hashed, the number of bytes for the salt and a hashing algorithm. Within the method we first generate a salt, then combine the bytes of the password and the salt in one list of bytes. We finally let the hashing algorithm hash the complete list of bytes and return the base 64 representation of both the salt and the hashed password. In fact it will be the hash of the password and the salt together.

Here’s a demo function with a 64-bit salt and 2 different hashing algorithms, SHA-256 and SHA-512:

private static void TestPasswordHasher()
	PasswordWithSaltHasher pwHasher = new PasswordWithSaltHasher();
	HashWithSaltResult hashResultSha256 = pwHasher.HashWithSalt("ultra_safe_P455w0rD", 64, SHA256.Create());
	HashWithSaltResult hashResultSha512 = pwHasher.HashWithSalt("ultra_safe_P455w0rD", 64, SHA512.Create());


Here is the output:



You can view the list of posts on Security and Cryptography here.


About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

2 Responses to How to hash passwords with a salt in .NET

  1. Hari Hari says:

    The problem is that the function requires “ultra_safe_P455w0rD” as a parameter. It is OK if its a server generated form like aspx, but what if if you use HTTP to call the function? The string has to be hashed at source itself, else the salt has to be sent to the client and then both hashes compared at the server. SHA256 produces same Hash in .net as well as in JS, so thats one option

    • Saci says:

      Yeah, I know, an old comment and I’m answering, but then, better late than never!

      Earlier today I found this article and tried to test it in C# + WPF.

      Had the same thoughts you had, then… I just moved the HashWithSalt method to private, and created another one (public) that returns a string[2] (to accomodate both the salt and digest), which just calls HashWithSalt and passes it the needed parameters, in this case, just the password string and lenght value.

      That enabled me to put it right in my database insert statement, so I can store bot the hashed password and the secret to confirm it later, during user authentication.

      I admit, not an elegant solution, but a good start, nonetheless.

      Sometimes, you’ll have to crack your skull to get results. But often, you’ll have to try to think in smaller factors, before going big time ass-kicking dev mode.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog


Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.

%d bloggers like this: