2

我目前正在将旧版 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?+&??>

我可以看到几乎相同,但为什么我得到了?人物

4

2 回答 2

5

这是第一个问题,至少:

string szReturn = objEncoder.GetString(btHashedDataBytes);

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

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

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

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

最后,这些天我会使用不同的散列算法,特别是对于密码。你能不能不使用现成的系统进行身份验证,实际上是由安全专家开发的?安全性很困难:我们最好把它留给知道如何正确操作的相对较少的人 :) 查看评论以获取更多建议。

于 2012-11-30T10:22:45.833 回答
1

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

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

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

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

于 2012-11-30T10:58:15.807 回答