using System.Security.Cryptography; using System.Text; namespace Lib_PasswordHashing { public class PasswordHashing { private readonly char[] SaltChars; private readonly HashAlgorithm Algorithm; /// /// Initialize Password hashing function /// /// Hashing algorithm /// Chars for generate salt in string form public PasswordHashing(HashAlgorithm? algorithm = null, string saltChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") { if (algorithm == null) { Algorithm = SHA512.Create(); //if not specified use default SHA512 } else { Algorithm = algorithm; //if algorithm specified use them } SaltChars = saltChars.ToCharArray(); //convert salt chars string to array for use him } /// /// Hash password with salt /// /// Password string /// Password hash and salt public HashedPassword HashPass(string password) { HashedPassword hp = GenerateSaltedPassword(password); //Generate Salted Password and salt byte[] sp = Encoding.UTF32.GetBytes(hp.Hash); //Convert salted password to Byte array byte[] hash = Algorithm.ComputeHash(sp); //Compute hash hp.Hash = Convert.ToBase64String(hash); //Convert Byte array to hash return hp; //return hash and salt } /// /// Compare password with hash and salt /// /// password /// hash /// salt /// Hash and Pass with salt same? public bool VerifyPass(string password, string Hash, string Salt) { string hash = Convert.ToBase64String( Algorithm.ComputeHash( Encoding.UTF8.GetBytes( GenerateSaltedPassword(password, Salt.ToArray()) ) ) ); //generate hash from password and salt if (hash == Hash) //is password correct? { return true; //yes } else //or { return false; //no } } /// /// Generate new salted Password /// /// Password /// Salted password and salt private HashedPassword GenerateSaltedPassword(string password) { char[] passwordSalt = GenerateSalt(password.Length); //Generate password salt return new HashedPassword() { Hash = GenerateSaltedPassword(password, passwordSalt), Salt = new string(passwordSalt) }; //return HashedPassword with salted password as Hash and Salt } /// /// Generate salted Password /// /// Password /// Salt for mix with password /// Salted password and salt private string GenerateSaltedPassword(string password, char[] passwordSalt) { List saltedPassword = new List(); //Initialize list for create Salted Password char[] passwordChars = password.ToCharArray(); //Transfer password string to Array for (int i = 0; passwordChars.Length >= i; i++) //Loop for mixing password and salt { saltedPassword.Add(passwordChars[i]); //Add password char to salted password saltedPassword.Add(passwordSalt[i]); //add salt char to salted password } return new string(saltedPassword.ToArray()); //Return string with saltedpassword } /// /// Generate salt /// /// Number of salt chars /// Salt private char[] GenerateSalt(int lenght) { List salt = new List(); //Create List for generate Salt string for (int i = lenght; i > 0; i--) //Loop for generate requested lenght of salt { salt.Add(SaltChars[Random.Shared.Next(0, SaltChars.Length - 1)]); //Random generate salt char } return salt.ToArray(); //return salt in array } } }