如何在C#中验证加盐和哈希密码

prk*_*ash 3 .net c# mysql cryptography

我使用以下方法对密码进行加盐和哈希处理

public string CreateSalt(int size)
{
    var rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
    var buff = new byte[size];
    rng.GetBytes(buff);
    return Convert.ToBase64String(buff);
}
public string GenerateSHA256Hash(String input, String salt)
{
    byte[] bytes = System.Text.Encoding.UTF8.GetBytes(input + salt);
    System.Security.Cryptography.SHA256Managed sha256hashstring =
        new System.Security.Cryptography.SHA256Managed();
    byte[] hash = sha256hashstring.ComputeHash(bytes);
    return Convert.ToBase64String(hash);
}
public void Submit1_click(object sender, EventArgs r)
{

    try
    {
        String salt = CreateSalt(10);
        String hashedpassword = GenerateSHA256Hash(password1.Text, salt);
        string MyConString = "SERVER=localhost;DATABASE=mydb;UID=root;PASSWORD=abc123;";
        MySqlConnection connection = new MySqlConnection(MyConString);
        string cmdText = "INSERT INTO authentication(agentlogin ,password ,question ,answer)VALUES ( @login, @pwd, @question, @answer)";
        MySqlCommand cmd = new MySqlCommand(cmdText, connection);
        cmd.Parameters.AddWithValue("@login", labeluname.Text);
        cmd.Parameters.AddWithValue("@pwd", hashedpassword);
        cmd.Parameters.AddWithValue("@question", ddlquestion.Text);
        cmd.Parameters.AddWithValue("@answer", txtanswer.Text);
        connection.Open();
        int result = cmd.ExecuteNonQuery();
        connection.Close();
        lblmsg.Text = "Registered succesfully";
        lblmsg.ForeColor = System.Drawing.Color.Green;
        Response.Redirect("index.aspx");
    }
    catch (Exception)
    {
        Console.Write("not entered");
        lblmsg.Text = "Registration failed!";
        lblmsg.ForeColor = System.Drawing.Color.Red;
        Response.Redirect("index.aspx");
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,我从上面获得了完全加密的密码,但是现在我无法使用在此输入的密码登录。登录时如何取消密码的密码?我认为我可以使用与加密相同的方法来取消哈希处理,但是盐化不会返回相同的值。以下是验证页面上的代码

    public string GenerateSHA256Hash(String input)
    {
        byte[] bytes = System.Text.Encoding.UTF8.GetBytes(input);
        System.Security.Cryptography.SHA256Managed sha256hashstring =
            new System.Security.Cryptography.SHA256Managed();
        byte[] hash = sha256hashstring.ComputeHash(bytes);
        return Convert.ToBase64String(hash);
    }

    public void Login_click(object sender, EventArgs r)
    {
        String hashedpassword = GenerateSHA256Hash(txtpassword.Text);
        string MyConString = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
        MySqlConnection con = new MySqlConnection(MyConString);
        MySqlCommand cmd = new MySqlCommand("select * from authentication where agentlogin=@username and password=@word", con);
        cmd.Parameters.AddWithValue("@username", txtusername.Text);
        cmd.Parameters.AddWithValue("@word", hashedpassword);
        MySqlDataAdapter sda = new MySqlDataAdapter(cmd);
        DataTable dt = new DataTable();
        sda.Fill(dt);
        con.Open();
        int i = cmd.ExecuteNonQuery();
        con.Close();
        if (dt.Rows.Count > 0)
        {
            Session["id"] = txtusername.Text;
            Response.Redirect("calendar.aspx");
            Session.RemoveAll();
        }
        else
        {
            lblmsg.Text = "Credential doesn't match!";
            lblmsg.ForeColor = System.Drawing.Color.Red;

        }

    }
Run Code Online (Sandbox Code Playgroud)

er-*_*sho 9

在用户表中创建一列UsernameHash然后Salt

用户注册

1)在您的注册表中输入信息usernamepassword从用户那里获取信息。

2)使用以下方法为输入的密码创建哈希和盐。

public class HashSalt
{
    public string Hash { get; set; }
    public string Salt { get; set; }
}

public static HashSalt GenerateSaltedHash(int size, string password)
{
    var saltBytes = new byte[size];
    var provider = new RNGCryptoServiceProvider();
    provider.GetNonZeroBytes(saltBytes);
    var salt = Convert.ToBase64String(saltBytes);

    var rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, saltBytes, 10000);
    var hashPassword = Convert.ToBase64String(rfc2898DeriveBytes.GetBytes(256));

    HashSalt hashSalt = new HashSalt { Hash = hashPassword, Salt = salt };
    return hashSalt;
}
Run Code Online (Sandbox Code Playgroud)

Rfc2898DeriveBytes类用于使用RFC2898规范生成哈希,该规范使用一种称为PBKDF2(基于密码的密钥派生功能#2)的方法,并且IETF(Internet工程任务组)目前建议将其用于新应用。

3)然后存储此HashSalt在数据库的用户记录。

public void Submit1_click(object sender, EventArgs r)
{
    //Your code here

    HashSalt hashSalt = GenerateSaltedHash(64, password1.Text);

    //Your code here

    cmd.Parameters.AddWithValue("@hash", hashSalt.Hash);
    cmd.Parameters.AddWithValue("@salt", hashSalt.Salt);

    //You code here
}
Run Code Online (Sandbox Code Playgroud)

用户登录

1)在您的登录表单中输入usernamepassword从用户那里获取。

2)Login_click从数据库中通过用户名获取用户。

3)将存储Hash并传递Salt到以下功能。

public static bool VerifyPassword(string enteredPassword, string storedHash, string storedSalt)
{
    var saltBytes = Convert.FromBase64String(storedSalt);
    var rfc2898DeriveBytes = new Rfc2898DeriveBytes(enteredPassword, saltBytes, 10000);
    return Convert.ToBase64String(rfc2898DeriveBytes.GetBytes(256)) == storedHash;
}
Run Code Online (Sandbox Code Playgroud)

4)然后通过验证用户密码登录。

public void Login_click(object sender, EventArgs r)
{
    //You code here

    User user = GetUserByUsername(txtUsername.Text);

    bool isPasswordMatched = VerifyPassword(txtpassword.Text, user.Hash, user.Salt);

    if (isPasswordMatched)
    {
        //Login Successfull
    }
    else
    {
        //Login Failed
    }

    //Your code here
}
Run Code Online (Sandbox Code Playgroud)

参考:有效的密码哈希