2012-11-23 162 views
34

升級到.Net 4.5後,我現在得到「System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile已過時」的警告,建議使用成員API代替。放棄替換FormsAuthentication.HashPasswordForStoringInConfigFile?

這對於新項目來說都非常好,但是在這個階段(用戶數據和散列密碼已存在),我不能很好地更改爲具有潛在不同散列方式的自定義成員資格提供程序。

這樣的問題推薦的方式是什麼?繼續使用「過時」的調用顯然不是建議的路徑,那麼它已被除「僅使用成員API」之外的其他內容所取代?

+0

HashPasswordForStoringInConfigFile是老了,有人建議更換替代那麼他們必須知道第二個參數是不是「MD5」或「SHA1」?是的,我知道這篇文章是舊的,但我偶然發現它,因爲我多年以來沒有使用過'HashPasswordForStoringInConfigFile'。 SHA1鹽+密碼的替換是好的 - 但在2016年的這一點,堅持SHA1是一個壞主意,更不用說可怕的MD5 –

回答

43

這是SHA1變體的解決方案。

 public static string GetSwcSHA1(string value) 
    { 
     SHA1 algorithm = SHA1.Create(); 
     byte[] data = algorithm.ComputeHash(Encoding.UTF8.GetBytes(value)); 
     string sh1 = ""; 
     for (int i = 0; i < data.Length; i++) 
     { 
      sh1 += data[i].ToString("x2").ToUpperInvariant(); 
     } 
     return sh1; 
    } 

對於MD5你只需要算法變爲:

MD5 algorithm = MD5.Create(); 

希望你不介意,只是要添加代碼的變種VB.NET上面:

Public Shared Function CreateHash(saltAndPassword) As String 
     Dim Algorithm As SHA1 = SHA1.Create() 
     Dim Data As Byte() = Algorithm.ComputeHash(Encoding.UTF8.GetBytes(saltAndPassword)) 
     Dim Hashed As String = "" 

     For i As Integer = 0 To Data.Length - 1 
      Hashed &= Data(i).ToString("x2").ToUpperInvariant() 
     Next 

     Return Hashed 
    End Function 
+0

非常有幫助,謝謝!如果我更新了你的VB.Net以包含函數聲明等,會不會有問題? –

+0

GetSwcSH1中的Swc是什麼意思? – Wes

2

理查德的回答對我很好。 這是從.NET Framework 4.5反編譯的代碼。 如果有任何事情更好,請使用它。我想這可能會快一點。

 public static string BinaryToHex(byte[] data) 
     { 
      if (data == null) 
      { 
       return null; 
      } 
      char[] hex = new char[checked((int)data.Length * 2)]; 
      for (int i = 0; i < (int)data.Length; i++) 
      { 
       byte num = data[i]; 
       hex[2 * i] = NibbleToHex((byte)(num >> 4)); 
       hex[2 * i + 1] = NibbleToHex((byte)(num & 15)); 
      } 
      return new string(hex); 
     } 

     private static char NibbleToHex(byte nibble) 
     { 
      int aChar = (nibble < 10 ? nibble + 48 : nibble - 10 + 65); 
      return (char)aChar; 
     } 
9

請告訴我推薦的方式向前像這樣的問題?繼續使用「過時」的調用顯然不是建議的路徑,那麼它已被除「僅使用成員API」之外的其他內容所取代?

純粹在.NET Framework中,最好的方法就是改變一切,讓密碼由PBKDF2,Bcrypt或Scrypt散列。 PBKDF2在.NET中由Rfc2898DeriveBytes Class提供。

第二個最好的辦法是使用密碼的兩個「版本」,結束了:

  • 版本0本來是老HashPasswordForStoringInConfigFile,但你可以更新那些塊狀的,離線,到版本1和刪除在任何人竊取他們之前,這些舊的哈希值已經全部散列出來,並且在貿易新聞中最終有可悲的90年代老式密碼哈希。
  • 版本1,它是現有HashPasswordForStoringInConfigFile值的PBKDF2!即你把你目前討厭的舊哈希和PBKDF2他們與一個新的隨機鹽和大量的迭代,並存儲結果。然後,當用戶想要登錄時,將密碼提供給@RichardBažant編寫的代碼,以便您擁有HashPasswordForStoringInConfigFile將返回的內容,然後然後將PBKDF2應用於該結果!
    • 即它實際上是Rfc2898DeriveBytes(HashPasswordForStoringInConfigFile(密碼)),PerUserSalt,YourIterations)
  • 第2版,這誰擁有版本1散列用戶都升級到。除「版本」以外的所有列都是相同的,但在計算並驗證版本1後,則計算Rfc2898DeriveBytes(密碼),PerUserSalt,YourIterations)並將版本1散列替換爲版本2散列(並將版本更改爲2,當然)。

第三個最好的辦法是第二個最好的方式,但只有版本1.請注意,這樣就在於DCC2瘋狂 - 你保持你的包裹舊的輸出新算法裏面

在這兩種情況下,你」 -111被存儲PBKDF2-HMAC-SHA-1的結果在數據庫中,所以你需要:

  • 密碼哈希(BINARY(20)) - 即PBKDF2輸出。
  • 你的鹽(BINARY(16),通過RNGCryptoServiceProvider Class每個用戶生成的)
  • 可選:PBKDF2迭代次數(INT,開始在數以萬計的,至多到之前你的服務器將CPU的最大約束加載;隨着您的硬件升級而增加)
    • 這允許您每次用戶輸入他們的(正確)密碼時都透明地提高安全級別。通過首先驗證它是否正確,然後用更高的迭代次數重新對其進行散列處理
  • 可選:A「版」(TINYINT),以便升級到另一種算法後比較容易,罪您可以同時擁有多個版本。

P.S.對於版本1或版本2更新的算法,Jither創建了一個支持PBKDF2-HMAC-SHA256,PBKDF2-HMAC-SHA512等的.NET庫; my Github repository包含它的一個變體,它具有一組合適的測試向量。

2

爲什麼不能利用.NET中最簡單的一個

public static string HashString(string inputString, string hashName) 
{ 
    var algorithm = HashAlgorithm.Create(hashName); 
    if (algorithm == null) 
    throw new ArgumentException("Unrecognized hash name", hashName); 

    byte[] hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString)); 
    return Convert.ToBase64String(hash); 
} 
+0

是的,HashAlgorithm非常靈活,我同意你的看法。然後,如果它是SHA1,那麼本質上它將被傳遞到創建方法,如HashAlgorithm.Create(「SHA-1」) –