C# Hashing algorithm class | Asp.Net | .Net Core

In this article, we’ll learn how to secure your password using already implemented C# hashing algorithm class and the importance of password hashing.

Users data is the most important thing in any application so it’s a developer responsibility to keep users data in the most secure way using best practices. When we talk about user account security, first thing comes in our mind is account password.

In any application, when a user creates his account the must have to enter a password. Account password with other account credentials always save in the database so if someone gains unauthorized access to the database then he can also see passwords for all accounts of that system.

Password Hashing

Password Hashing performs a one-way transformation on password, changing the password into another String, called the hashed password. “One-way” means that it is not possible to turn the hashed password back into the original password using the sample algorithm in reverse order.

For Password Hashing, there are several built-in algorithms in all languages(C# also provides e.g. MD5) but for a more secure password, hashing algorithm must be a combination of some built-in algorithms.

I’m going to share a password hashing class for Asp.Net Code. Using this class you can easily Hash a password in a secure string before saving it into a database and also match password with hashed string with a function.

So here’s the Code

using System;
using System.Security.Cryptography;

namespace MyProject.Helpers
{
    public sealed class SecurePasswordHasherHelper
    {
        /// <summary>
        /// Size of salt
        /// </summary>
        private const int SaltSize = 16;

        /// <summary>
        /// Size of hash
        /// </summary>
        private const int HashSize = 20;

        /// <summary>
        /// Creates a hash from a password
        /// </summary>
        /// <param name="password">the password</param>
        /// <param name="iterations">number of iterations</param>
        /// <returns>the hash</returns>
        public static string Hash(string password, int iterations)
        {
            //create salt
            byte[] salt;
            new RNGCryptoServiceProvider().GetBytes(salt = new byte[SaltSize]);

            //create hash
            var pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations);
            var hash = pbkdf2.GetBytes(HashSize);

            //combine salt and hash
            var hashBytes = new byte[SaltSize + HashSize];
            Array.Copy(salt, 0, hashBytes, 0, SaltSize);
            Array.Copy(hash, 0, hashBytes, SaltSize, HashSize);

            //convert to base64
            var base64Hash = Convert.ToBase64String(hashBytes);

            //format hash with extra information
            return string.Format("$MYHASH$V1${0}${1}", iterations, base64Hash);
        }
        /// <summary>
        /// Creates a hash from a password with 10000 iterations
        /// </summary>
        /// <param name="password">the password</param>
        /// <returns>the hash</returns>
        public static string Hash(string password)
        {
            return Hash(password, 10000);
        }

        /// <summary>
        /// Check if hash is supported
        /// </summary>
        /// <param name="hashString">the hash</param>
        /// <returns>is supported?</returns>
        public static bool IsHashSupported(string hashString)
        {
            return hashString.Contains("$MYHASH$V1$");
        }

        /// <summary>
        /// verify a password against a hash
        /// </summary>
        /// <param name="password">the password</param>
        /// <param name="hashedPassword">the hash</param>
        /// <returns>could be verified?</returns>
        public static bool Verify(string password, string hashedPassword)
        {
            //check hash
            if (!IsHashSupported(hashedPassword))
            {
                throw new NotSupportedException("The hashtype is not supported");
            }

            //extract iteration and Base64 string
            var splittedHashString = hashedPassword.Replace("$MYHASH$V1$", "").Split('$');
            var iterations = int.Parse(splittedHashString[0]);
            var base64Hash = splittedHashString[1];

            //get hashbytes
            var hashBytes = Convert.FromBase64String(base64Hash);

            //get salt
            var salt = new byte[SaltSize];
            Array.Copy(hashBytes, 0, salt, 0, SaltSize);

            //create hash with given salt
            var pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations);
            byte[] hash = pbkdf2.GetBytes(HashSize);

            //get result
            for (var i = 0; i < HashSize; i++)
            {
                if (hashBytes[i + SaltSize] != hash[i])
                {
                    return false;
                }
            }
            return true;
        }
    }

}

Add this class to your project and use it like this:

string hashed_password = SecurePasswordHasherHelper.Hash("12345");


12345 equivalent hashed string is $MYHASH$V1$10000$PMCjQg77vX6piW11bo8XKwM2dKjwMk8qOWVj25sMEonKoN2e 

Every time when you’ll hash 12345, you’ll get a different string

You can Validate password in this way

if (SecurePasswordHasher.Verify("12345",hashed_password))
{
     return "Password is Valid";
}

 

LEAVE A REPLY

Please enter your comment!
Please enter your name here