问题
我的应用程序(我将用C#编写)使用密钥派生方法(Rfc2898DeriveBytes,4000次迭代)和salt来生成密码的“哈希”。然后将此哈希发送到数据库,以便用户以后可以使用该密码对其帐户进行身份验证。
到目前为止应该是安全的,但在此之后,我想在相同的密码上使用Rfc2898DeriveBytes来生成一个密钥,然后可以使用进行加密。现在,我要这样做的方法是使用相同方法的5000次迭代来获得不同的密钥,但我担心如果存储在数据库中的哈希被泄露(或者我被迫透露它),那么它将是可能以某种方式得出第二个密钥。这可能吗?
潜在解决方案
对于如何最好地改进这一过程,我将不胜感激。我会发布代码,但我还没写过。
答案 0 :(得分:3)
您可以从一个密码派生多个密钥。
您是否为不同目的使用不同的盐,或生成更长的密钥并将其中的一部分用于不同目的,取决于您是否需要同时使用不同的密钥。例如,假设用户登录,然后希望能够加密和解密内容而无需重新输入密码。在这种情况下,生成双长度密钥更有效,并使用派生密钥的前半部分进行身份验证,将后半部分用于加密。使用不同的盐生成两个密钥需要大约两倍的时间。
另一方面,如果要求用户输入密码进行身份验证,然后再进行其他加密时间,则不妨选择两种盐。
根据您的提议,泄露存储在数据库中的身份验证哈希不会立即导致泄密。也就是说,你不能简单地迭代哈希函数; PBKDF2的每次迭代都使用密码作为输入。但它确实意味着只需要1000次迭代就可以将密码作为加密密钥进行测试,而且几乎不会受到字典攻击的保护。
顺便说一下,5000次迭代还不够。 50000次迭代将是一个良好的开端。
答案 1 :(得分:3)
为了便于参考,我正在编写一个答案的建议。
迭代次数
虽然这不是我的问题的一部分,但erickson指出,对于Rfc2898DeriveBytes(C#的PBKDF2方法)的5000次迭代太少,建议至少50,000次。
在寻找更多信息之后,似乎50,000到1,000,000之间的迭代次数很多,但请记住,速度和安全性之间存在反比关系:随着迭代次数的增加,安全性也会提高,导出密钥所需的时间(这就是为什么它更安全)。
<强>解决方案强>
虽然根据erickson的说法,第一把钥匙不能用于确定第二把钥匙,但它确实使蛮力攻击变得更容易。因此,可以使用以下任何解决方案来解决此问题:
拒绝解决方案
<强>结论强>
感谢大家的帮助,如果您有任何进一步的见解请发表评论,我会尽力添加。
答案 2 :(得分:2)
在Rfc2898DeriveBytes
的两次调用之间使用不同的盐可以解决您的问题。
这样想,两个不同的用户使用相同的密码,知道一个人的哈希值是另一个吗?只有两个用户使用相同的盐!
你正在做的事情没有什么不同,只需使用两种好的盐来同时使用Rfc2898DeriveBytes
,你就可以了。无需更改两种方法的迭代次数,只需更改盐即可。
没有理由需要重新使用盐,盐不是秘密信息。大多数文件加密实现都将盐(也称为IV
)放在加密blob的前面。
对于您的其他解决方案“如何使用SHA作为数据库哈希,使用Rfc作为加密密钥?”这是一个非常坏主意。对数据库使用SHA意味着它们更容易获得原始密码,然后他们可以使用更简单的任务来完成解密基于Rfc的更难的任务。