.NET 4.0中的错误加密错误
今天我将我的web应用程序移至.net 4.0并且Forms Auth刚刚停止工作。经过几个小时的挖掘我的SqlMembershipProvider(简化版本的内置SqlMembershipProvider)后,我发现HMACSHA256散列不一致。这是加密方法:.NET 4.0中的错误加密错误
internal string EncodePassword(string pass, int passwordFormat, string salt)
{
if (passwordFormat == 0) // MembershipPasswordFormat.Clear
return pass;
byte[] bIn = Encoding.Unicode.GetBytes(pass);
byte[] bSalt = Convert.FromBase64String(salt);
byte[] bAll = new byte[bSalt.Length + bIn.Length];
byte[] bRet = null;
Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
if (passwordFormat == 1)
{ // MembershipPasswordFormat.Hashed
HashAlgorithm s = HashAlgorithm.Create(Membership.HashAlgorithmType);
bRet = s.ComputeHash(bAll);
} else
{
bRet = EncryptPassword(bAll);
}
return Convert.ToBase64String(bRet);
}
传递相同的密码和salt两次返回不同的结果!它在.NET 3.5中工作完美。
任何人都知道任何重大更改,还是已知的错误?
更新:当我指定SHA512作为哈希算法,一切工作正常,所以我相信这是在实施HMACSHA256散列算法的缺陷在.NET 4.0中
谢谢! 安德烈
我相信已经有在.NET 4.0中某些与安全相关的变化来看看这个...
http://www.asp.net/(S(ywiyuluxr3qb2dfva1z5lgeg))/learn/whitepapers/aspnet4/breaking-changes
那伸出的第一个明显的事情是这样的......
默认哈希算法现在 HMACSHA256
ASP.NET使用加密和 哈希算法帮助保护数据 如表单身份验证Cookie 和查看状态。默认情况下,ASP.NET 4 现在使用HMACSHA256算法对 散列操作进行cookie并查看 状态。早期版本的ASP.NET 使用旧版HMACSHA1算法。
您的应用程序可能会受到影响,如果 您混合运行ASP.NET 2.0/ASP.NET 4种 环境下,如数据形成 验证Cookie必须努力 across.NET框架版本。要 配置ASP.NET 4 Web应用程序 使用旧HMACSHA1算法, 添加在 Web.config文件中的以下设置:
<machineKey validation="SHA1" />
您是否明确设置你的散列算法或只是让asp.net决定...如果它现在使用了不同的默认值,它可能只是随机抽取任何旧的散列算法,因为定义的算法不再受支持。
说了这样的话,M $可能已经退休了,你可能是因为这个原因,bug手....脚....我只是意识到我需要测试我的CMS ......这一切都没有发生在我身上。
感谢您的高举,希望我的想法能够帮助我们俩!
我也遇到了这个问题。
在我的情况下,最终目标是能够动态地设置connectionString(而不是在web.config中进行硬编码)。我通过下载MS为ASP提供的源代码来完成此操作。NET提供程序并更改某些获取连接字符串的内部功能。
但是,这一切都为.NET 2.0,看起来就像上面的Andrey贴出的代码。一旦我全部到位,我发现我无法登录到我的网站。所以在搜索后我发现了这篇文章。谢谢!
我继续下载.NET Framework 4.0代码和(如果有人想知道),这里是EncodePassword方法的新版本。我打算将其复制到我旧版本的SqlMembershipProvider中,以便我可以使用新的加密方法并能够再次登录到ASP.NET 4.0网站!
private string EncodePassword(string pass, int passwordFormat, string salt)
{
if (passwordFormat == 0) // MembershipPasswordFormat.Clear
return pass;
byte[] bIn = Encoding.Unicode.GetBytes(pass);
byte[] bSalt = Convert.FromBase64String(salt);
byte[] bRet = null;
if (passwordFormat == 1)
{ // MembershipPasswordFormat.Hashed
HashAlgorithm hm = GetHashAlgorithm();
if (hm is KeyedHashAlgorithm) {
KeyedHashAlgorithm kha = (KeyedHashAlgorithm) hm;
if (kha.Key.Length == bSalt.Length) {
kha.Key = bSalt;
} else if (kha.Key.Length < bSalt.Length) {
byte[] bKey = new byte[kha.Key.Length];
Buffer.BlockCopy(bSalt, 0, bKey, 0, bKey.Length);
kha.Key = bKey;
} else {
byte[] bKey = new byte[kha.Key.Length];
for (int iter = 0; iter < bKey.Length;) {
int len = Math.Min(bSalt.Length, bKey.Length - iter);
Buffer.BlockCopy(bSalt, 0, bKey, iter, len);
iter += len;
}
kha.Key = bKey;
}
bRet = kha.ComputeHash(bIn);
}
else {
byte[] bAll = new byte[bSalt.Length + bIn.Length];
Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
bRet = hm.ComputeHash(bAll);
}
} else {
byte[] bAll = new byte[bSalt.Length + bIn.Length];
Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
bRet = EncryptPassword(bAll, _LegacyPasswordCompatibilityMode);
}
return Convert.ToBase64String(bRet);
}
编辑:试图将这一个方法复制到旧版本的SqlMembershipProvider是一个坏主意。变化太多了。 :(