8

我对安全性知之甚少(我需要找到基础知识的基本解释),并试图提出一种合理的方法来使用 .Net 将用户密码存储在数据库中。

这是我目前的解决方案:

private static byte[] HashPassword(string password)
{
   using (var deriveBytes = new Rfc2898DeriveBytes(password, 10))
   {
      byte[] salt = deriveBytes.Salt;
      byte[] key  = deriveBytes.GetBytes(20);

      return salt.Concat(key).ToArray();  //Return Salt+Key
   }
}

我将 HashPassword() 的结果存储在数据库中。要检查用户的密码,我这样做:

var salt = //1st  10 bytes stored in the DB
var key  = //Next 20 bytes stored in the DB 
using (var deriveBytes = new Rfc2898DeriveBytes(password, salt))
{
   byte[] newKey = deriveBytes.GetBytes(20);

   if (newKey.SequenceEqual(key) == false)  //Check if keys match
   {
      return "No Match";
   }
   else { return "Passwords match"; }

我的问题是盐是否需要像这样随机存储在数据库中,或者我是否可以生成一个 10 字节的盐并将其存储在我的代码中,并始终使用相同的盐来保存自己将盐存储在数据库中存储密钥?

此外,如果有人看到我正在做的任何其他问题,我将不胜感激任何建议。

4

2 回答 2

29

我的问题是盐是否需要像这样随机存储在数据库中,或者我是否可以生成一个 10 字节的盐并将其存储在我的代码中,并始终使用相同的盐来保存自己将盐存储在数据库中存储密钥?

绝对不。

如果您甚至问这个问题,您根本不了解盐的用途。

salt 的目的是让攻击者更难以使用预先计算的散列通用密码表。如果盐总是相同的,那么攻击者只需使用该盐预先计算一个散列的通用密码表。

让我更清楚地说明这一点。假设攻击者已经获得了您的密码数据库,并且正在闲暇时对所有存储的散列进行攻击,以计算出与散列对应的密码是什么。如果每个盐都不同,那么攻击者必须对数据库中的每个条目进行的攻击。如果每个盐都是相同的,那么攻击一个用户会攻击每个用户

此外:假设您为每个用户使用相同的盐。假设两个用户有相同的密码。并且假设攻击者已经获得了密码数据库。攻击者现在知道哪两个用户有相同的密码,因为他们有相同的加盐哈希,并且可以合理地假设这是数据库中最弱的密码。攻击者可以将她的精力(无论可能是什么)集中在攻击该用户上。一旦她知道该用户的密码,该用户很有可能在其他系统上使用了该用户名和弱密码,攻击者现在可以在没有密码文件的情况下进行攻击。

您想了解安全性很好;你试图用你的理解水平编写一个真正的密码系统是很糟糕的。如果这是一个必须保护真实用户的真实系统,请使用由专家构建的系统,或聘请您自己的专家。您将创建一个无法破坏的系统,而不是攻击无法破坏的系统。

此外:您在互联网上向陌生人寻求安全帮助。陌生人,你不知道他们是否知道他们在说什么,或者只是在编造一些东西。找一个真正的安全专家(那不是我——我是语义分析器专家)。构建安全系统是最困难的编程任务之一。你需要专业的帮助。

有关基本密码认证方案的简要介绍,请参阅我的系列文章:

http://blogs.msdn.com/b/ericlippert/archive/tags/salt/

于 2012-02-08T15:10:31.737 回答
1

您不需要应用随机盐,但如果您这样做,您的密码将更加安全。显然,如果您确实应用了随机盐,那么您需要将其与散列密码一起存储在数据库中,以便您可以检查提供的密码。

一个快速的谷歌揭示了这篇文章,这可能会对你有所帮助。

于 2012-02-08T14:58:35.273 回答