实施散列的最佳实践?

时间:2011-06-14 01:30:34

标签: c# .net sql-server c#-3.0

我需要实现散列(我不是指加密)来制作一些数据字段(密码或一些不需要以原始格式返回的细节,而只需要匹配在db)安全。能否请您建议实施散列的最佳实践。我将使用C#和SQL Server,它将成为一个网站。

3 个答案:

答案 0 :(得分:5)

好了,现在你说你正在保护你有一些选择的密码。

.NET框架有一些内置算法 - MD5,SHA1,SHA2。 MD5和SHA1现在被认为是过时且危险的,而是坚持使用SHA256。

例如(摘自我的书)

static byte[] GenerateSaltedHash(string password, byte[] salt)
{
  byte[] plainText = Encoding.UTF8.GetBytes(password);
  HashAlgorithm algorithm = new SHA256Managed();

  byte[] plainTextWithSaltBytes = 
    new byte[plainText.Length + salt.Length];

  for (int i = 0; i < plainText.Length; i++)
  {
    plainTextWithSaltBytes[i] = plainText[i];
  }
  for (int i = 0; i < salt.Length; i++)
  {
    plainTextWithSaltBytes[plainText.Length + i] = salt[i];
  }

  byte[] hash = algorithm.ComputeHash(plainTextWithSaltBytes);            
}

现在盐可以停止预先计算的哈希查找(哈希本身已经不够用了,人们预先计算了字典词汇的哈希值等)。但你怎么得盐?嗯,它确实是任何独特的值,通常是一组随机的字节。

    public byte[] GenerateSalt(int length)
    {
        salt = new byte[length];

        // Strong runtime pseudo-random number generator, on Windows uses CryptAPI
        // on Unix /dev/urandom
        RNGCryptoServiceProvider random = new RNGCryptoServiceProvider();

        random.GetNonZeroBytes(salt);

        return salt;
    }

所以你先打电话给GenerateSalt(32)来获取盐(32只是一个例子,如果你愿意,可以更长。你需要将盐与密码一起存储 - 你不必担心保护它一点都不。

最后你需要一个比较功能。当您想要检查密码时,您将获取用户输入,获取该用户的salt,生成所提供密码和存储盐的哈希,然后进行比较。你可以使用像

这样的东西
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
public static bool ConstantCompare(byte[] array1, byte[] array2)
{
    const byte Zero = 0;
    int maxLength = array1.Length > array2.Length ? array1.Length : array2.Length;
    bool wereEqual = array1.Length == array2.Length;

    byte[] paddedArray1 = new byte[maxLength];
    byte[] paddedArray2 = new byte[maxLength];
    for (int i = 0; i < maxLength; i++)
    {
        paddedArray1[i] = array1.Length > i ? array1[i] : Zero;
        paddedArray2[i] = array2.Length > i ? array2[i] : Zero;
    }
    bool compareResult = true;
    for (int i = 0; i < maxLength; i++)
    {
        compareResult = compareResult & paddedArray1[i] == paddedArray2[i];
    }
    return compareResult & wereEqual;
}

当然,我应该指出ASP.NET成员函数执行salt和hash,因此它们应该是第一个调用点。如果其他人已经完成了这项工作,那就没有必要自己动手了。

答案 1 :(得分:1)

这是一个使用PB​​KDF2进行散列的ONTOP键的API,现在是最好的做法。

https://sourceforge.net/projects/pwdtknet

答案 2 :(得分:0)

我认为你误解了什么是哈希。您不使用哈希来“使数据字段安全”,因为哈希只能在一个方向上计算。计算并存储数据的哈希值,仅存储哈希值,以后您将无法检索数据。

您可能需要加密数据。这是一个完全不同的蠕虫,它有自己的问题:你如何存储和保护解密密钥,使用什么加密算法,你在数据库级别进行加密(sql server支持这个)或应用程序级别?如何实施加密传输,并防止最终用户复制数据?