所以我使用.NET中的Rcfc2898DeriveBytes类将密码哈希到数据库
一切正常用于散列和存储最终散列和盐。
但是,我在确定存储在散列密码时该类运行的迭代次数时遇到了问题。
在谷歌搜索之后,我只看到它应该存储在密码哈希之前,但是我不确定如何以一种方式来解决这个问题,以便在我稍后更改数字的情况下检索该数字(如果不存储迭代,则更改将破坏旧密码。
我看到bcrypt会为你做这一切,但我没有为项目添加库的奢侈。
存储这个数字的最佳方法是什么?我将如何进行这样的操作,以便它可以检索,而不是仅仅在存储时丢失在哈希中(一旦我将它从哈希中分离出来,我将如何从哈希中分离出来)? / p>
提前感谢您提供任何建议和信息!
答案 0 :(得分:1)
原则上,您根本不必存储迭代量。就像你不必存储散列类型一样,如果你保持一致。
我会提出一些略有不同的东西:存储一个包含版本号的字节(带前缀),从零开始,就在salt&之前。哈希值。此版本号与迭代次数,哈希方法,字符编码方法以及PBKDF2相关联。如果要升级到更好的协议,只需将01
存储为初始字节,并将其与新参数链接。通过这种方式,您可以区分旧样式密码和新样式。
通常情况下,只有当用户输入密码时才能升级,因为散列不可逆,因此升级迭代次数并不容易。
答案 1 :(得分:1)
我在下面的网址找到了我要找的内容。
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方法将我的值保存到数据库供以后使用。我使用ValidatePassword让它们退出让我再次使用。它像魅力一样工作,允许我为salt和hash创建字节大小,以及基于所需强度的迭代次数变量。这些值只存储在Web / App配置文件中。
感谢大家的答案!
答案 2 :(得分:0)
看看bcrypt如何在这里存储哈希值: What column type/length should I use for storing a Bcrypt hashed password in a Database?
因此,如果你只打算改变迭代,你可以选择这样简单的事情:
$<number of iterations>$<hash>