Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rfc2898DeriveBytes how to verify the password which is store in database as hash value

how to verify password which is store in database as hash value

When I verify the password hash with the database value it will never be the same because it generates the random salt.

how to append the salt in order to verify and test.

Below is the code I am using for hashing and verify the hashed password.

My Code :

/// <summary>
        /// Generate the value from bytes.
        /// </summary>
        /// <param name="password"></param>
        /// <param name="iterationCount"></param>
        /// <returns></returns>
        private static string GenerateHashValue(string password)
        {
            return Convert.ToBase64String(GenerateHashBytes(password));
        }

        /// <summary>
        /// Hashing the password using PBKDF2
        /// </summary>
        /// <param name="password"></param>
        /// <param name="iterationCount"></param>
        /// <returns></returns>
        private static byte[] GenerateHashBytes(string password)
        {
            byte[] hashValue;
            //create salt
            byte[] salt = GenerateRandomSalt();
            var valueToHash = string.IsNullOrEmpty(password) ? string.Empty : password;
            using (var pbkdf2 = new Rfc2898DeriveBytes(valueToHash,salt, iterationCount))
            {
                hashValue = pbkdf2.GetBytes(DerivedKeyLength); 
            }
            return hashValue;
        }

        public static bool VerifyPassword(string password, string correctHash)
        {
            byte[] hash;
            byte[] OriginalHash = Encoding.ASCII.GetBytes(correctHash);
            hash = GenerateHashBytes(password); 
            return SlowEquals(hash, OriginalHash);
        }

        private static bool SlowEquals(byte[] a, byte[] b)
        {
            var diff = (uint)a.Length ^ (uint)b.Length;
            for (int i = 0; i < a.Length && i < b.Length; i++)
            {
                diff |= (uint)(a[i] ^ b[i]);
            }
            return diff == 0;
        }

        /// <summary>
        /// Used to generate the random string to append hash.
        /// </summary>
        /// <returns></returns>
        private static byte[] GenerateRandomSalt()
        {
            /*We are using the RNGCryptoServiceProvider class to create a Cryptography Secure Pseudo-Random Number Generator that will generate the level of randomness and uniqueness we require for a salt.*/
            var csprng = new RNGCryptoServiceProvider();
            var salt = new byte[SaltByteLength];
            csprng.GetBytes(salt);
            return salt;
        }
like image 203
Kapil Avatar asked Sep 11 '17 03:09

Kapil


1 Answers

You will have to create a salt AND store it in your database along with the password hash.

Upon hashing the password, you request the salt for user X (or whatever) from the DB, check if it exists, and apply the salt to your hash.

It would look like this (pseudo-code with a little of your provided code):

var salt = GetSaltFromDB();
if (salt == null) //Not yet in DB
    salt = GenerateSalt(); //This also saves the salt to DB
using (var pbkdf2 = new Rfc2898DeriveBytes(valueToHash, salt, iterationCount))
{
    hashValue = pbkdf2.GetBytes(DerivedKeyLength); 
}
like image 160
Blacktempel Avatar answered Oct 13 '22 03:10

Blacktempel