所以我正在使用 .NET 中的 Rcfc2898DeriveBytes 类对数据库的密码进行哈希处理
对于哈希和存储最终哈希和盐,一切都很好。
但是,我在计算哈希密码时存储类运行的迭代次数时遇到了问题。
谷歌搜索后,我只看到它应该存储在密码哈希前面,但我不确定如何以一种使号码可检索的方式做到这一点,以防我以后更改号码(如果不存储迭代,更改会破坏旧密码)。
我看到 bcrypt 会为您完成这一切,但我没有奢侈地为项目添加库。
存储此数字的最佳方法是什么,我将如何做到这一点,以便它是可检索的,而不仅仅是在存储时丢失在哈希中(一旦我取回它,我将如何将其与哈希分开)?
提前感谢您的任何建议和信息!
原则上,您根本不需要存储迭代次数。就像您不必存储哈希类型一样,如果您保持一致。
我会提出一些稍微不同的东西:存储一个包含版本号的单字节(前缀),从零开始,就在盐和哈希之前。此版本号与迭代次数、哈希方法、字符编码方法,当然还有 PBKDF2 相关联。如果要升级到更好的协议,只需将01
存储为初始字节并将其与新参数链接即可。通过这种方式,您可以区分旧样式密码和新样式。
通常,只有在用户输入密码时才能升级,因为哈希不可逆,因此不容易升级迭代次数。
我在下面的URL中找到了我正在寻找的内容。
https://cmatskas.com/-net-password-hashing-using-pbkdf2/
相关代码在这里:
public class PasswordHash
{
public const int SALT_BYTE_SIZE = 24;
public const int HASH_BYTE_SIZE = 20;
public const int PBKDF2_ITERATIONS = 1000;
public const int ITERATION_INDEX = 0;
public const int SALT_INDEX = 1;
public const int PBKDF2_INDEX = 2;
public static string HashPassword(string password)
{
var cryptoProvider = new RNGCryptoServiceProvider();
byte[] salt = new byte[SALT_BYTE_SIZE];
cryptoProvider.GetBytes(salt);
var hash = PBKDF2(password, salt, PBKDF2_ITERATIONS, HASH_BYTE_SIZE);
return PBKDF2_ITERATIONS + ":" +
Convert.ToBase64String(salt) + ":" +
Convert.ToBase64String(hash);
}
public static bool ValidatePassword(string password, string correctHash)
{
char[] delimiter = { ':' };
var split = correctHash.Split(delimiter);
var iterations = Int32.Parse(split[ITERATION_INDEX]);
var salt = Convert.FromBase64String(split[SALT_INDEX]);
var hash = Convert.FromBase64String(split[PBKDF2_INDEX]);
var testHash = PBKDF2(password, salt, iterations, hash.Length);
return SlowEquals(hash, testHash);
}
}
我采用HashPassword方法将我的值保存到数据库中以供以后使用。 我使用验证密码将它们重新取出供我再次使用。 它就像一个魅力,允许我根据所需的强度调整盐和哈希的字节大小,以及迭代次数。 这些值仅存储在 Web/应用程序配置文件中。
谢谢大家的回答!
bcrypt 如何存储哈希:我应该使用什么列类型/长度在数据库中存储Bcrypt散列密码?
因此,如果您只打算更改迭代,则可以选择像这样简单的事情:
$<number of iterations>$<hash>