【发布时间】:2014-11-11 23:42:59
【问题描述】:
我对密码学完全陌生,但正在学习。我从网上的研究中总结了许多不同的建议,并创建了自己的类来处理哈希、盐、键拉伸以及相关数据的比较/转换。
在研究了用于密码学的内置 .NET 库后,我发现我所拥有的仍然只有 SHA-1。但我得出的结论是,这还不错,因为我使用了哈希过程的多次迭代。对吗?
但是,如果我想从更强大的 SHA-512 开始,我该如何在下面的代码中实现它?提前致谢。
using System;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Cryptography;
public class CryptoSaltAndHash
{
private string strHash;
private string strSalt;
public const int SaltSizeInBytes = 128;
public const int HashSizeInBytes = 1024;
public const int Iterations = 3000;
public string Hash { get { return strHash; } }
public string Salt { get { return strSalt; } }
public CryptoSaltAndHash(SecureString ThisPassword)
{
byte[] bytesSalt = new byte[SaltSizeInBytes];
using (RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider())
{
crypto.GetBytes(bytesSalt);
}
strSalt = Convert.ToBase64String(bytesSalt);
strHash = ComputeHash(strSalt, ThisPassword);
}
public static string ComputeHash(string ThisSalt, SecureString ThisPassword)
{
byte[] bytesSalt = Convert.FromBase64String(ThisSalt);
Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(
convertSecureStringToString(ThisPassword), bytesSalt, Iterations);
using (pbkdf2)
{
return Convert.ToBase64String(pbkdf2.GetBytes(HashSizeInBytes));
}
}
public static bool Verify(string ThisSalt, string ThisHash, SecureString ThisPassword)
{
if (slowEquals(getBytes(ThisHash), getBytes(ComputeHash(ThisSalt, ThisPassword))))
{
return true;
}
return false;
}
private static string convertSecureStringToString(SecureString MySecureString)
{
IntPtr ptr = IntPtr.Zero;
try
{
ptr = Marshal.SecureStringToGlobalAllocUnicode(MySecureString);
return Marshal.PtrToStringUni(ptr);
}
finally
{
Marshal.ZeroFreeGlobalAllocUnicode(ptr);
}
}
private static bool slowEquals(byte[] A, byte[] B)
{
int intDiff = A.Length ^ B.Length;
for (int i = 0; i < A.Length && i < B.Length; i++)
{
intDiff |= A[i] ^ B[i];
}
return intDiff == 0;
}
private static byte[] getBytes(string MyString)
{
byte[] b = new byte[MyString.Length * sizeof(char)];
System.Buffer.BlockCopy(MyString.ToCharArray(), 0, b, 0, b.Length);
return b;
}
}
注意:我参考了https://crackstation.net/hashing-security.htm 的很多做法。 slowEquals 比较方法是通过防止分支来规范执行时间。 SecureString 的用途是在这个类和我的 Web 应用程序中的其他类和页面之间使用加密形式的密码传递。虽然此站点将通过 HTTPS 进行,但最好多做一点以确保事情尽可能安全,同时仍在合理范围内。
在我的代码中,我将密钥字符串设置为 128 字节(尽管有时它会变大,这很好),哈希大小设置为 1KB,迭代次数设置为 3,000。它比典型的 64 字节盐、512 字节哈希和 1,000 或 2,000 次迭代要大一些,但登录速度和应用性能仍然是一个极低的优先级。
想法?
【问题讨论】:
-
代码审查的类似问题:Secure password hashing
标签: c# hash cryptography salt sha