我们目前在 .net 中使用HMACSHA512,具有128Char(64byte)验证密钥salt 是 64 char 随机生成的 字符串。我们在数据库上为散列的 base64 字符串结果分配了 2048 长度。这将是一个面向公众的网站。 这种方法是否合理,还是应该改为另一种方法,例如 Rfc2898DeriveBytes?
public string HashEncode(string password, string salt, string validationKey) {
byte[] hashKey = BosUtilites.HexStringToByteArray(validationKey);
var sha512 = new HMACSHA512(hashKey);
var hashInput = BosUtilites.StringToByteArray(password + salt);
byte[] hash = sha512.ComputeHash(hashInput);
return Convert.ToBase64String(hash);
}
public string GenerateSimpleSalt(int Size = 64) {
var alphaSet = new char[64]; // use 62 for strict alpha... that random generator for alphas only
//nicer results with set length * int i = 256. But still produces excellent random results.
//alphaset plus 2. Reduce to 62 if alpha requried
alphaSet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890#=".ToCharArray();
var tempSB = GenerateRandomString(Size, alphaSet);
return tempSB.ToString();
}
public StringBuilder GenerateRandomString(int Size, char[] alphaSet) {
using (var crypto = new RNGCryptoServiceProvider()) {
var bytes = new byte[Size];
crypto.GetBytes(bytes); //get a bucket of very random bytes
var tempSB = new StringBuilder(Size);
foreach (var b in bytes) { // use b , a random from 0-255 as the index to our source array. Just mod on length set
tempSB.Append(alphaSet[b%(alphaSet.Length)]);
}
return tempSB;
}
EDIT2:如果有人通过谷歌找到这个,我已经包括了 在工作站测试中的平均样本是 300 毫秒。这在登录期间不应该太明显。并且不再需要验证密钥。这是一种解脱:-)
SCrypt package installed via nuget. and rfc2898 PBKDF2 changed to be large number or iterations but only 20bytes output. SAme CPU time.
默认情况下,新密码以 SCRYPT 编码,
<package id="CryptSharpOfficial" version="2.0.0.0" targetFramework="net451" />
// save salt, hash algorithm used and resulting encoding on user record
public string PasswordEncode(string password, byte[] salt, HashAlgorithm hashAlgorithm ) {
switch (hashAlgorithm) {
case HashAlgorithm.PBKDF2:
var deriver2898 = new Rfc2898DeriveBytes(password, salt,<Use a number around 50K>); // approx 300msecs on workstation
byte[] hash = deriver2898.GetBytes(20); //
return Convert.ToBase64String(hash);
case HashAlgorithm.Scrypt:
var key = Encoding.UTF8.GetBytes(password);
byte[] hashScrypt = SCrypt.ComputeDerivedKey(key: key, salt: salt,
cost: 65536, // must be a power of 2 !, on PC, singlethread this is approx 1 sec
blockSize: 8,
parallel: 1,
maxThreads: 1,
derivedKeyLength: 128);
return Convert.ToBase64String(hashScrypt);
default:
throw new ArgumentOutOfRangeException("hashAlgorithm");
}
}