2012-06-12 65 views
0

zetetic有一個非常好的加密庫,它包含對bcrypt2的支持。它看起來應該足夠簡單,可以合併到ASP.NET成員資格提供程序中(實際上,可以找到有關默認提供程序的說明here)。我正在使用NHibernate成員資格提供程序(發現here)似乎在其EncodePassword函數中硬編碼SHA1哈希格式。我的問題是,這應該如何適應與BCrypt2(特別是Zetetic的包裝)。這是我非常害怕出錯的原因,我不願意自己刺傷它,以免它「應用」,但卻有一些我沒有資格找到的隱藏缺陷。ASP.NET MVC - 將zetetic安全性與NHibernate成員提供者集成

private string EncodePassword(string password) 
     { 
      string encodedPassword = password; 

      switch (PasswordFormat) 
      { 
       case MembershipPasswordFormat.Clear: 
        break; 
       case MembershipPasswordFormat.Encrypted: 
        encodedPassword = 
         Convert.ToBase64String(EncryptPassword(Encoding.Unicode.GetBytes(password))); 
        break; 
       case MembershipPasswordFormat.Hashed: 
        HMACSHA1 hash = new HMACSHA1(); 
        hash.Key = HexToByte(_machineKey.ValidationKey); 
        encodedPassword = 
         Convert.ToBase64String(hash.ComputeHash(Encoding.Unicode.GetBytes(password))); 
        break; 
       default: 
        throw new ProviderException("Unsupported password format."); 
      } 

      return encodedPassword; 
     } 

回答

1

您是在修改基於NHibernate的成員資格提供程序,還是堅持使用它開箱即用?如果是後者,它看起來沒有任何可擴展性。

的ASP.NET SqlMembershipProvider的工作原理是接受散列算法的名稱,使人聯想經由HashAlgorithm.Create(name)一個實例,並然後行爲有點不同,如果該算法類型被證明是一個KeyedHashAlgorithm或常規(非鍵控)的HashAlgorithm。 Zetetic.Security軟件包只是提供一點粘合劑,使BCrypt和PBKDF2與該模型兼容。

來自NHMembershipProvider的示例代碼無法利用此優勢,因爲它直接依賴於HMACSHA1。我會注意到,HMACSHA1不是一個安全的算法,也不是爲所有可接受的用戶使用靜態鹽(它幾乎不比鹽好)。應用程序ValidationKey和HMACSHA1僅用於消息完整性。

這裏有一個例子:

public class HashDemo 
{ 
    private static readonly RNGCryptoServiceProvider s_rng = new RNGCryptoServiceProvider(); 

    public string HashPassword(string pwd, string hashName) 
    { 
     var alg = HashAlgorithm.Create(hashName); 

     if (alg == null) 
      throw new ArgumentException("Invalid hash name", "hashName"); 

     byte[] tohash = System.Text.Encoding.UTF8.GetBytes(pwd); 

     var ka = alg as KeyedHashAlgorithm; 

     if (ka != null) 
     { 
      if (ka.Key == null || ka.Key.Length == 0) 
      { 
       byte[] key = new byte[20]; 

       s_rng.GetBytes(key); 

       ka.Key = key; 
      } 
      else 
      { 
       s_rng.GetBytes(ka.Key); 
      } 
      // TODO: return base64(ka.Key || alg.ComputeHash(tohash)) 
     } 
     else 
     { 
      var salt = new byte[20]; 

      s_rng.GetBytes(salt); 

      using (var ms = new System.IO.MemoryStream(salt)) 
      { 
       ms.Write(tohash, 0, tohash.Length); 

       tohash = ms.ToArray(); 
      } 
      // TODO: return base64(salt || alg.ComputeHash(tohash)) 
     } 
    } 
} 
+0

我修改基於NHibernate的提供商,所以很自由地進行修改。這聽起來(糾正我,如果我錯了)就像我需要拔出EncodePassword實現並插入一個調用HashAlgorithm.Create? –

+0

還有一個想法 - 如果您要滾動MembershipProvider,您可能需要爲散列alg名稱和參數以及散列輸出分配單獨的列,以防您想從(例如)BCrypt更改爲SCrypt或更改工作因素,與BCrypt哈希的人仍然可以登錄。 – SKradel

+0

謝謝@SKradel - 你的回答非常有見地。我不想使用zetetics解決方案,因爲直接從EncodePassword函數的switch語句中的MembershipPasswordFormat.Hashed情況調用bcrypt(如果我沒有使用自定義提供程序,我肯定會使用zetetic解決方案。 ..)。我非常喜歡在每條記錄中存儲算法和工作因子的想法,並且當用戶的工作因素與網站使用的當前工作因素不匹配時,我計劃再進一步並在登錄時重新密碼。 –

相關問題