C# 初学者散列&;腌制

C# 初学者散列&;腌制,c#,hash,md5,C#,Hash,Md5,所以我对编程(C#)相当陌生,尤其是一般的密码学。我尝试通过使用MD5哈希算法复制几个函数并学习它的工作原理来学习一些。然后我连接到一个数据库,并进行了登录和重置密码功能。然而,当我尝试使用相同的密码时,问题出现了。我意识到,不管我在散列值中添加随机生成的salt,散列值都将是相同的 string MD5(string input) { MD5 md5 = new MD5CryptoServiceProvider();

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

    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;
    }
这是我用来生成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());
        }
    }
如下所示,哈希值相同,但salt不同。我加盐的方式是我不应该加盐的吗

bec78d2acfd2eb4f5d7da2fd231bad1c     0x21B5F48096E31092FCCD20EE22EF9B3C307ADDC1C31B8D84          
bec78d2acfd2eb4f5d7da2fd231bad1c     0xC063774EBBD4FAED268811C84D70662F4DDB53BCA52A6720  
对此是否有合理的解释,或者代码是否有问题? 另外,我对哈希算法并不熟悉,这是我偶然发现的,我想了解更多。有没有更简单的方法?我读过其他似乎很容易使用的算法,但正如我所说的,我对此并不熟悉。散列算法之间的安全性差异无关紧要。我确实读过MD5很旧,不太安全,但它已经足够我使用了

提前感谢。

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

salt
是一个字节数组,通过将
+
字符串一起使用,它的
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

在第
hashedPassword=MD5(MD5(tempHash+salt))
行中,您正在将一个字符串与一个字节数组连接起来。您应该将salt转换为字符串,或者更好的做法是:将字节传递给
MD5()
。“将字节传递给MD5()”的确切含义是什么?您已经需要将传递给
MD5()
函数的字符串转换为字节数组(第3行)。如果你的
MD5
函数只接受了一个字节数组,那么你就可以得到密码的字节,与salt的字节连接,然后将得到的字节数组交给
MD5()
。哦,这真是太棒了。我怎么没想到呢。添加salt后,是否可以将带salt的哈希密码转换回字符串?当然,您始终可以通过
Encoding.UTF8.GetString(bytes)
(将
UTF8
替换为您正在使用的任何文本编码)从字节数组转到字符串。这很有意义。但是,将salt从数据库中提取为字符串,并将其与文本框中写入的哈希密码进行比较时,我遇到了一些问题。那么,将其转换回
字节[]
。这就是为什么我在SQL中将其存储为
varbinary
。我该如何解决这个问题呢?嗯,我不知道您的实现是否偏离了轨道,但看起来您正在存储实际的盐。但是因为你的杂烩从来都不是用盐做的,所以你永远也找不到匹配的。是的,我现在明白你的意思了,这个例子很有帮助。谢谢你!