2012-11-23 410 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”) –