是否取代FormsAuthentication.HashPasswordForStoringInConfigFile?

时间:2012-11-23 10:34:11

标签: .net forms-authentication

升级到.Net 4.5后,我现在收到“System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile已过时”的警告,建议改为使用成员资格API。

这对新项目来说非常好,但是在这个阶段(存在用户数据和散列密码),我不能很好地改变为具有可能不同的散列方式的自定义成员资格提供者。

对于像这样的问题,推荐的方法是什么?继续使用“过时”调用显然不是建议的路径,所以除了“只使用成员资格API”之外,它是否被其他东西取代?

4 个答案:

答案 0 :(得分:49)

这是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

答案 1 :(得分: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哈希的用户升级到。除“version”之外的所有列都是相同的,但在计算并验证版本1之后,您计算Rfc2898DeriveBytes(密码),PerUserSalt,YourIterations)并将版本1散列替换为版本2散列(并将版本更改为2,当然)。

第三种最好的方法是第二种最好的方法,但只有版本1.请注意,这种方式是DCC2疯狂 - 你继续将旧输出包装在更新的算法中

在这两种情况下,您都将PBKDF2-HMAC-SHA-1结果存储在数据库中,因此您需要:

  • 密码哈希(BINARY(20)) - 即PBKDF2输出。
  • 你的盐(BINARY(16),由RNGCryptoServiceProvider Class生成的每位用户)
  • 可选:PBKDF2迭代次数(INT,数万次启动,直到服务器在最大负载下受CPU限制;随着硬件升级而增加)
    • 这使您可以在每次用户输入(正确)密码时透明地提高安全级别。首先验证密码是否正确,然后以更高的迭代次数重新散列它
  • 可选:“版本”(TINYINT),以便以后升级到其他算法更容易,因为您可以同时激活多个版本。

P.S。对于版本1或版本2的新算法,Jither创建了一个支持PBKDF2-HMAC-SHA256,PBKDF2-HMAC-SHA512等的.NET库; my Github repository包含一个带有一组合理测试向量的变体。

答案 2 :(得分: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;
        }

答案 3 :(得分: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);
}