C#MD5CryptoServiceProvider

时间:2012-11-30 10:20:50

标签: c# encryption md5

我目前正在将旧版ASP.NET 1.1应用程序转换为.NET 4 MVC 3应用程序。

我正在查看密码加密,并在旧代码中编写了一个例程来使用MD5CryptoServiceProvider。

        private string EncryptText(string szText)
        {
            try
            {
                UTF8Encoding objEncoder = new UTF8Encoding();                
                MD5CryptoServiceProvider objMD5Hasher = new MD5CryptoServiceProvider();
                Byte[] btHashedDataBytes = objMD5Hasher.ComputeHash(objEncoder.GetBytes(szText));
                string szReturn = objEncoder.GetString(btHashedDataBytes);
                objEncoder = null;
                objMD5Hasher = null;

                return szReturn;
            }
            catch
            {               
                return "";
            }
        }

我已经编写了一个快速的.NET 4控制台应用程序并复制了这个函数,因此我可以对数据库中的当前密码进行比较(以确保MD5函数仍然为我提供相同的输出)

            string encTxt = encryptor.EncryptText("fbloggsPass12345");

            using (SqlConnection conn = new SqlConnection("Server=server;Database=db;User Id=sa;Password=1111;"))
            {
                conn.Open();
                using (SqlCommand cmd = new SqlCommand())
                {
                    cmd.Connection = conn;
                    cmd.CommandType = System.Data.CommandType.Text;                   

                    cmd.CommandText = "UPDATE SiteUsers SET Token = '" + encTxt + "' WHERE PKey = 10";
                    if (cmd.ExecuteNonQuery() > 0)
                        Console.WriteLine("Updated");
                    else
                        Console.WriteLine("Failed");

                }
                conn.Close();
            }

            Console.ReadLine();

然而,目前数据库中的密码是什么!?MGF +&>我得到的输出是 !? MGF +& >当我在数据库中存储时,转换为???!??? MGF?+& ??>

我能看到的几乎是一样的,但为什么我得到了?字符

2 个答案:

答案 0 :(得分:5)

这是第一个问题,至少是:

string szReturn = objEncoder.GetString(btHashedDataBytes);

您正在尝试使用哈希,就好像它是UTF-8编码的文本一样。它不是 - 它只是任意的二进制数据。

如果您需要将任意二进制数据转换为文本,则应使用类似Base64(例如Convert.ToBase64String)或十六进制的内容。

(另外,我会强烈建议你不要以你现在这样做的方式“处理”异常。你为什么要隐藏这样的问题?为什么你在变量超出范围之前将变量设置为null?)

哦,不要直接在SQL中包含值 - 请改用参数化的SQL。

最后,我现在会使用不同的哈希算法,尤其是密码。您是否可以使用现成的系统进行身份验证,这实际上是由安全专家开发的?安全性很难:我们最好把它留给相对较少知道如何正确行事的人:)请参阅评论以获得更多建议。

答案 1 :(得分:1)

低影响升级的标准技术是使用旧散列作为新散列方案的输入。这适用于普通的MD5哈希值。

不幸的是,您通过非二进制安全编码(UTF8)发送二进制哈希。这将每隔一个字符替换为0xFFFD,有效地将输出大小减半为64位。这大大削弱了升级计划,但并未致命。

我将现有哈希值升级到PBKDF2(legacyHash, salt),然后在用户登录时用新哈希PBKDF2(password, salt)替换哈希值,该哈希值不依赖于旧方案。几个月后,为所有尚未登录的用户触发密码重置,摆脱传统的基于哈希的密码。

对于新方案,我将使用在 Rfc2898DeriveBytes Class中实现的PBKDF2-SHA-1。使用足够的迭代,至少10000次。