我目前正在将旧版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?+& ??>
我能看到的几乎是一样的,但为什么我得到了?字符
答案 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次。