【问题标题】:Beginner hashing & salting初学者哈希和加盐
【发布时间】:2016-03-16 23:18:21
【问题描述】:

所以我对编程 (C#) 尤其是一般的密码学相当陌生。我尝试通过使用 MD5 散列算法复制几个函数并学习它的工作原理来学习一些。然后我连接到数据库并进行了登录和重置密码功能。但是,当我尝试使用相同的密码时出现了问题,我意识到无论我在哈希值中添加随机生成的盐,哈希值都会变成相同的。

    string MD5(string input)
    {
        MD5 md5 = new MD5CryptoServiceProvider();                                  
        byte[] bytes = md5.ComputeHash(Encoding.Unicode.GetBytes(input));          
        string result = BitConverter.ToString(bytes).Replace("-", String.Empty); 
        return result.ToLower();
    }
    public static byte[] GenerateSalt()
    {
        RNGCryptoServiceProvider saltGenerator = new RNGCryptoServiceProvider();
        byte[] salt = new byte[24];
        saltGenerator.GetBytes(salt);
        return salt;
    }

这是我生成盐和散列输入字符串的函数。这是通过在WinForms中填写两个文本框来重置密码的代码。

        private void HashNewPassword(out byte[] salt, out string hashedPassword)
    {
        string tempHash;
        salt = null;
        hashedPassword = null;

        if (txtPassword1.Text == txtPassword2.Text)
        {
            tempHash = txtPassword1.Text;
            salt = GenerateSalt();
            hashedPassword = MD5(MD5(tempHash + salt));
        }
        else
        {
            throw new Exception();
        }
    }

最后,点击偶数功能:

        private void btnFinished_Click(object sender, EventArgs e)
    {
        try
        {
            string hashedPassword;
            byte[] salt;

            HashNewPassword(out salt, out hashedPassword);
            AddPasswordToDB(salt, hashedPassword);
        }
        catch (Exception error)
        {
            MessageBox.Show(error.Message + "   :   " + error.GetType().ToString());
        }
    }

如下所示,哈希值相同,但盐值不同。我是否以不应该的方式添加盐?

bec78d2acfd2eb4f5d7da2fd231bad1c     0x21B5F48096E31092FCCD20EE22EF9B3C307ADDC1C31B8D84          
bec78d2acfd2eb4f5d7da2fd231bad1c     0xC063774EBBD4FAED268811C84D70662F4DDB53BCA52A6720  

对此有合理的解释,还是代码有问题? 另外,我不熟悉哈希算法,只是我偶然发现并想了解更多信息。有没有更简单的方法来做到这一点?我读过其他似乎很容易使用的算法,但正如我所说,我对此并不熟悉。哈希算法之间的安全差异无关紧要。我确实读过 MD5 很旧而且不是那么安全,但它对我的使用来说已经绰绰有余了。

提前致谢。

【问题讨论】:

  • hashedPassword = MD5(MD5(tempHash + salt)) 行上,您将字符串与字节数组连接起来。您应该将盐转换为字符串,或者更好:将字节传递给MD5()
  • 我明白了。 “将字节传递给 MD5()”到底是什么意思?
  • 您已经必须将传递给 MD5() 函数的字符串转换为字节数组(第 3 行)。如果您的MD5 函数只接受一个字节数组,那么您可以获得密码的字节,与盐的字节连接,然后将生成的字节数组提供给MD5()
  • 哦,这真是太棒了。我怎么没想到。添加盐后是否可以将带有盐的哈希密码转换回字符串?
  • 当然,您始终可以通过Encoding.UTF8.GetString(bytes)(用UTF8 替换您使用的任何文本编码)从字节数组中转到字符串。

标签: c# hash md5


【解决方案1】:

在不涉及安全方面的情况下,我相信您会得到相同的哈希值,因为您没有将盐连接为字符串:tempHash + salt

salt 是一个字节数组,通过使用+string,它的ToString() 方法在连接之前被调用。这将不会产生具有实际值的字符串。

尝试将数组转换为实际字符串:

System.Text.Encoding.Default.GetString(salt)

一个小例子来进一步阐明这种行为:

byte[] salt = new byte[] {67,79,79,76};
Console.WriteLine(salt.ToString()); // prints System.Byte[]

string saltAsString = System.Text.Encoding.Default.GetString(salt);
Console.WriteLine(saltAsString); // prints COOL

【讨论】:

  • 这是有道理的。但是,我从数据库中提取盐作为字符串,将其与文本框中写入的散列密码进行比较时遇到问题。好吧,将其转换回byte[]。这就是我在 SQL 中将其存储为 varbinary 的原因。我将如何解决这个问题?
  • 好吧,我不知道您的实现是否偏离了方向,但您似乎正在存储实际的盐。但是由于您的哈希从未使用该盐创建,因此您永远不会得到匹配。
  • 是的,我现在明白你的意思了,这个例子很有帮助。欣赏!
猜你喜欢
  • 2011-05-27
  • 2015-09-27
  • 1970-01-01
  • 2012-11-04
  • 2011-12-06
  • 1970-01-01
  • 2010-11-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多