为什么我需要使用Rfc2898DeriveBytes类(在.NET中),而不是直接使用密码作为密钥或IV?


76

使用Rfc2898DeriveBytes和仅使用之间有什么区别Encoding.ASCII.GetBytes(string object);

我在这两种方法中都取得了相对的成功,前一种方法是一个比较冗长的方法,而后者则简单易懂。两者似乎都允许您最终做同样的事情,但是我很难理解使用前者而不是后者的意义。

我已经掌握的基本概念是,您可以将字符串密码转换为字节数组,以用于例如对称加密类AesManaged。通过RFC类,但是在创建rfc对象时可以使用salt值和密码。我认为它更安全,但这充其量也是毫无根据的猜测!另外,它还允许您返回一定大小的字节数组,类似的东西。

以下是一些示例,向您展示我来自哪里:

byte[] myPassinBytes = Encoding.ASCII.GetBytes("some password");

要么

string password = "P@%5w0r]>";
byte[] saltArray = Encoding.ASCII.GetBytes("this is my salt");
Rfc2898DeriveBytes rfcKey = new Rfc2898DeriveBytes(password, saltArray);

现在,可以使用“ rfcKey”对象在对称加密算法类上设置.Key或.IV属性。

即。

RijndaelManaged rj = new RijndaelManaged ();
rj.Key = rfcKey.Getbytes(rj.KeySize / 8); 
rj.IV = rfcKey.Getbytes(rj.Blocksize / 8);

'rj'应该准备好了!

令人困惑的部分...因此,我不能只使用我的“ myPassInBytes”数组来帮助设置“ rj”对象,而不是使用“ rfcKey”对象吗?

我曾尝试在VS2008中执行此操作,但直接的答案是“否”。但是你们是否有一个更好的受过良好教育的答案,那就是为什么在我上面提到的其他替代方法上使用RFC类呢?


这个问题与考试的修改和准备有关!
IbrarMumtaz 2010年

Answers:


184

您确实真的不想直接将用户密码用作加密密钥,尤其是使用AES时。

Rfc2898DeriveBytes是PBKDF2的实现。它的作用是反复哈希用户密码和盐。这有多个好处:

首先,您可以使用任意大小的密码-AES仅支持特定的密钥大小。

其次,盐的添加意味着您可以使用相同的密码来生成多个不同的密钥(假设盐不是常量,就像您的示例中那样)。这对于密钥分离很重要;在不同的上下文中重用密钥是破坏密码系统的最常见方法之一。

多次迭代(默认为1000)降低了密码猜测攻击的速度。考虑有人试图猜测您的AES密钥。如果您只是使用密码,这将很简单-只需尝试每个可能的密码作为密钥。另一方面,对于PBKDF2,攻击者首先必须为每个密码猜测执行1000次哈希迭代。因此,尽管它只会稍微降低用户的速度,但对攻击者的影响却不成比例。(实际上,使用更高的迭代次数是很普遍的;通常建议使用10000)。

这也意味着最终输出密钥是均匀分布的。例如,如果您使用密码,则密钥的128位中的16位通常为0(ASCII高位)。在那里,即使忽略了密码猜测,也使键搜索比原来应容易的65536倍。

最后,AES具有与特定的密钥攻击相关的特定漏洞。当攻击者知道一些使用多个密钥加密的数据并且它们之间存在某种已知(或猜测)关系时,可能会发生相关的密钥攻击。例如,如果使用“我的AES密钥很烂”的密码密钥(对于AES-128,为16字节)和“我的AES密钥删除”来加密数据,则可能会发生相关的密钥攻击。当前最广为人知的攻击实际上并不能以这种方式破坏完整的AES,但是随着时间的推移,它们逐渐变得越来越好-就在上周,一种新的攻击被发布,它使用以下方法破坏了13轮(共14轮)AES-256相关的按键攻击。依靠这样的攻击不会随着时间的推移而变得越来越好是非常不明智的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.