使用Rfc2898DeriveBytes从明文密码创建安全密码时盐的重要性

6
我想在我的C# .NET应用程序中加入文件的加密和解密。场景很简单:用户A将AES256加密文件发送给用户B。明文密码通过不同的通道(例如电话或其他方式)进行交换。
据我所知,我应该使用Rfc2898DeriveBytes将用户的明文密码转换为更安全的密码,可能需要进行10000轮的计算。(参见这篇文章
但是,在我的场景中,我不理解盐的作用。通常,在哈希密码时会使用盐来防止字典攻击。但是,在我的场景中,PBKDF2算法通过添加PBKDF2轮所需的额外计算来弥补短或容易猜测的明文密码的弱点。
如果我选择一个随机盐,则接收者也需要知道该盐才能正确解密。如果我使用恒定盐,则黑客可以轻松地反向工程我的代码,并使用我的恒定盐运行暴力攻击(尽管由于PBKDF2迭代,速度会非常缓慢)。
据我所知,在我的场景中,我别无选择,只能使用恒定盐并强制执行良好的明文密码规则以弥补恒定盐的弱点。我的假设是正确的吗?
2个回答

6

在密码哈希(和密钥派生)的上下文中,盐用于防止预计算攻击,例如彩虹表攻击。

请注意,盐必须对于每个密码都是不同和不可预测的(最好是随机的)。此外,请注意,盐不需要保密 - 这就是密码的作用。通过保持盐的机密性,您不会获得任何安全性。

您的情况下推荐的方法是每次加密文件时生成一个随机盐,并将盐与密文一起传输。

顺便问一下,您使用AES-256有特定的原因吗?由于额外的轮数,它比AES-128慢大约40%,并且它没有实际的安全优势(特别是在基于密码的加密的情况下)。

另外值得考虑使用像PGP这样的成熟标准而不是从加密基元构建自己的协议,因为构建安全协议非常困难,即使专家也不总是做得正确。


2
攻击者可以预先计算出大量常见密码的密钥,并使用该表格对任意数量的消息进行攻击,而无需进行进一步的工作。 - ntoskrnl
“构建自己的协议”是什么意思?如果我使用.NET框架中的RijndaelManaged来加密一个使用安全生成的密码的文件,有什么问题吗?既然我使用的是由专家开发的库,那么它不应该从设计上就是安全的吗?还是我没有理解你的观点? - Marco
2
正确使用的盐可以防止多目标攻击,而不仅仅是预计算。 盐的不可预测性也不是那么重要。 - CodesInChaos
1
“如果我使用.NET框架中的RijndaelManaged有什么问题吗?” 仅因为一个构建块是由专家编写的,并不意味着您在其上构建的系统是安全的。例如,您可能会错误地使用IV,忘记MAC,错误地使用MAC,... 使用低级加密API很棘手,大多数开发人员都会犯错。” - CodesInChaos
1
+1 虽然句子“通过保密盐值无法提高安全性。”是不正确的。例如,盐值可以由公开已知的盐和代码中的静态盐值组成。在这种情况下,您需要知道数据库中的盐值和代码中的盐值。如果这些可被不同角色访问,那么这个技巧可以用来提供另一层安全性。 - Maarten Bodewes
显示剩余9条评论

0

你的假设是正确的。如果他们有密码访问权限,他们也将能够访问盐。我见过的BCrypt实现将迭代次数、哈希和盐都放在同一个结果字符串中!

这个想法是:即使盐和迭代次数已知,你的哈希也应该是安全的。(如果我们总是能知道攻击者不知道盐、迭代次数甚至算法,那么安全性就会变得容易得多!直到攻击者礼貌地拒绝阅读我们的盐,在遭受攻击时我们必须假设他们将能够访问它们。)所以你是对的,如果他们有几台超级计算机和几百万年的计算时间,他们可以使用暴力破解。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接