首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在c#中验证加盐和哈希密码

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

Stack Overflow用户
提问于 2018-09-03 17:07:29
回答 1查看 15.9K关注 0票数 6

我使用下面的方法对密码进行加盐和散列。

代码语言:javascript
复制
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");
    }
}

因此,我从上面获得了完全加密的密码,但现在我无法使用输入的密码登录。如何在登录时解开密码?我想我可以使用与加密相同的方法来对其进行解散列,但是加盐不会返回相同的值。以下是验证页面上的代码

代码语言:javascript
复制
    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;

        }

    }
EN

回答 1

Stack Overflow用户

发布于 2018-09-03 17:13:08

在将盐添加到密码并对其进行散列之前,您必须存储盐。

因此,当有人尝试登录时,您可以将密码与存储的盐连接起来,然后您可以对其进行散列,并将其与base中现有的散列进行比较。

因此,您的用户表应该至少包含以下3列: username、hashedpassword、salt

更长的解释:散列函数是确定性的,但不可逆,所以当用户第一次创建他的密码时:

  • 生成salt
  • 将密码和salt
  • 连接在一起,对密码和salt
  • 的连接结果字符串进行散列处理<

>F211>同时保存散列和salt代码

所以你有: hashedpassword = hashingfunction(password+salt)

当您尝试登录时:

  • 您可以获取作为输入的登录和密码
  • 使用该登录,您可以检索基本密码中的散列和盐您已经有了hashingfunction
  • so,您可以处理密码,将结果与hashingfunction(password_entered_by_user+salt)
  • you进行比较,如果是相同的

,则登录用户

将盐放在散列密码旁边并不会降低它的安全性:盐的目的是防止使用rainbowtable

如果有人闯入你的数据库,他可能会瞄准你用户的email+password,因为大多数人在很多不同的地方重复使用相同的密码和电子邮件。

现在,由于散列函数是不可逆的,所以攻击者唯一能做的就是尝试猜测密码并创建一个字典:

代码语言:javascript
复制
guessed_password => hash(guessed_password)

例如:

代码语言:javascript
复制
pet345 => 23FD7890F0F3FA3AE468F37CB900402A1F1977CF926F3452CA519056E16985AB
lola78 => 876B42DC10A0822CC52B894DC7517C784A542B43FB033B4A93635ADA67946B2E
lola79 => A7DCAF5195463FA367CDEA6F23688C1280EC98F4AF2B08BC3469D2496537D48D
lola80 => 8D8E1CF212F5DDC3CA1D510900382DF945625A9AE1584CE0D539B2C4D73717CB

如果hash( guessed_password )在您的数据库中,那么他知道这个(这些)用户的密码是guessed_password。

他可以生成一个有数十亿guessed_passwords的字典,由于许多用户并不使用真正强的密码,因此他很可能能够在他的字典中找到大量的用户散列。因此,如果他为“lola80”和“lola79”生成散列,并且这些是您的两个用户的密码,那么他知道这一点。

现在,如果您为输入的每个密码添加一个随机的盐,那么对于每个盐,他必须生成一个完整的字典,因为他必须这样做:

代码语言:javascript
复制
guessed_password + salt = hash(guessed_password + salt)

对于使用salt '09ç@p$‘的用户A,他必须生成一个完整的词典,其中每个单词都以'09ç@p$’结尾

现在,如果他想要猜测与salt 'Yuè45gh‘关联的用户B的密码,他必须生成另一个字典,其中每个单词都以'Yuè45gh’结尾。

基本上,它通过your_number_of_users因素减慢了猜测用户密码的过程。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52146528

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档