实施散列的最佳实践?

use*_*510 6 .net c# sql-server c#-3.0

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

blo*_*art 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);            
}
Run Code Online (Sandbox Code Playgroud)

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

    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;
    }
Run Code Online (Sandbox Code Playgroud)

因此,您首先要调用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;
}
Run Code Online (Sandbox Code Playgroud)

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