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
}
}
}