使用c#保护用户密码 - Rfc2898DeriveBytes vs SHA512

时间:2017-01-05 05:26:18

标签: c# security hash passwords salt

我一直在阅读有关在数据库中保护用户密码的信息(https://crackstation.net/hashing-security.htm)。理解基本思路 - 生成随机Salt,将其附加到密码并散列密码。

所以这就是我所做的(我没有在这里放一些转换成字符串的方法):

RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create();
byte[] rndBytes = new byte[512];
randomNumberGenerator.GetBytes(rndBytes);
string salt = ToHexString(rndBytes);

var sha512Hasher = SHA512.Create();
string hashedPwd = ToHexString(sha512Hasher.ComputeHash(GetBytes(pwd + salt)))

根据该文章,这是有保障的,但通过使用"键拉伸"可以更加安全。根据我的理解,哈希做得较慢(使用参数)使密码更难以使用。

所以这就是我所做的:

RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create();
byte[] salt = new byte[512];
randomNumberGenerator.GetBytes(salt);
Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(user.Password, salt, 1000);
byte[] hashBytes = k1.GetBytes(512);
string hash = ToHexString(hashBytes);

现在我的问题是:

  1. SHA512Rfc2898DeriveBytes之间有什么区别?哪个更安全?
  2. 我应该使用更少的盐来进行更多的迭代吗?它会让它更安全吗?
  3. 在1000次迭代中它运行得非常快 - 它应该有多慢?半秒钟?一秒?这里有什么经验法则?
  4. 在数据库上 - 我应该将字节数组转换为字符串并存储字符串,还是应该将字节数组存储在二进制数据字段中?
  5. 编辑(其他问题)

    1. 如果我重复使用SHA512重复1000次 - 是否会提供相同的安全性?

1 个答案:

答案 0 :(得分:4)

  1. SHA512和Rfc2898DeriveBytes有什么区别?
  2. SHA512是加密散列函数,而Rfc2898DeriveBytes是密钥派生函数。正如您已经写过的那样,哈希函数太快并且太强大了,这就是为什么我们需要像BCrypt,SCrypt,PBKDF2或Argon2这样的成本因子的函数。据我所知,Rfc2898DeriveBytes使用带有SHA1的HMAC实现PBKDF2。这回答了另一个问题,即迭代的SHA比Rfc2898DeriveBytes 更少安全。

    1. 我应该用更少的盐进行更多的迭代吗?
    2. 盐和成本因素无关,具有不同的用途。盐阻止了彩虹表的使用,迭代是蛮力攻击的对策。您可以从我的tutorial获取更多关于安全密码存储的信息。所以不,不要让盐变短。

      1. 它应该多慢?
      2. 当然这取决于您的服务器和您对安全性的要求,较慢意味着更难以蛮力。对于单个哈希,经验法则是50 milliseconds

        1. 在数据库上 - 我应该将字节数组转换为字符串吗?
        2. 这取决于你。字符串在备份,迁移和调试时更容易处理,而字节数组在数据库中占用的空间更少。也许您还应该查看BCrypt.Net,它会生成包含salt的输出字符串,并且很容易存储在单个数据库字段[string]中。