.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是一个坏主意。变化太多了。 :(