我需要实现散列(我不是指加密)来制作一些数据字段(密码或一些不需要以原始格式返回的细节,而只需要匹配在db)安全。能否请您建议实施散列的最佳实践。我将使用C#和SQL Server,它将成为一个网站。
答案 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)
这是一个使用PBKDF2进行散列的ONTOP键的API,现在是最好的做法。
答案 2 :(得分:0)
我认为你误解了什么是哈希。您不使用哈希来“使数据字段安全”,因为哈希只能在一个方向上计算。计算并存储数据的哈希值,仅存储哈希值,以后您将无法检索数据。
您可能需要加密数据。这是一个完全不同的蠕虫,它有自己的问题:你如何存储和保护解密密钥,使用什么加密算法,你在数据库级别进行加密(sql server支持这个)或应用程序级别?如何实施加密传输,并防止最终用户复制数据?