2010-05-13 58 views
4

今天我將我的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中

謝謝! 安德烈

回答

2

我相信已經有在.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 ......這一切都沒有發生在我身上。

感謝您的高舉,希望我的想法能夠幫助我們倆!

2

我也遇到了這個問題。

在我的情況下,最終目標是能夠動態地設置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是一個壞主意。變化太多了。 :(