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

时间:2023-03-27
本文介绍了为什么我需要使用 Rfc2898DeriveBytes 类(在 .NET 中)而不是直接使用密码作为密钥或 IV?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

使用 Rfc2898DeriveBytes 和只使用 Encoding.ASCII.GetBytes(string object); 有什么区别?

What is the difference between using Rfc2898DeriveBytes and just using Encoding.ASCII.GetBytes(string object);?

我在这两种方法上都取得了相对的成功,前者是一种更冗长的方法,而后者则简单明了.两者似乎都允许你最终做同样的事情,但我很难看出使用前者而不是后者的意义.

I have had relative success with either approach, the former is a more long winded approach where as the latter is simple and to the point. Both seem to allow you to do the same thing eventually but I am struggling to the see the point in using the former over the latter.

我能掌握的基本概念是可以将字符串密码转换成要用于例如对称加密类 AesManaged 的字节数组.通过 RFC 类,但您可以在创建 rfc 对象时使用盐值和密码.我认为它更安全,但充其量仍然是一个没有受过教育的猜测!此外,它还允许您返回一定大小的字节数组,以及类似的东西.

The basic concept I have been able to grasp is that you can convert string passwords into byte arrays to be used for e.g a symmetric encryption class, AesManaged. Via the RFC class but you get to use salt values and password when creating your rfc object. I assume its more secure but still thats an uneducated guess at best! Also that it allows you to return byte arrays of a certain size, well something like that.

这里有几个例子告诉你我来自哪里:

Here are a few examples to show you where I am coming from:

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 属性关于对称加密算法类.

The 'rfcKey' object can now be used towards setting up the the .Key or .IV properties on a symmetric encryption algorithm class.

即.

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

'rj' 应该准备好了!

'rj' should be ready to go !

令人困惑的部分......所以我可以不只使用我的rfcKey"对象吗?'myPassInBytes' 数组来帮助设置我的 'rj' 对象?

The confusing part ... so rather than using the 'rfcKey' object can I not just use my 'myPassInBytes' array to help set-up my 'rj' object?

我曾尝试在 VS2008 中执行此操作,但立即回答是否定的.但是对于为什么使用 RFC 类而不是我上面提到的其他替代方案,你们有更好的回答吗?

I have tried doing this in VS2008 and the immediate answer is NO. But have you guys got a better educated answer as to why the RFC class is used over the other alternative I have mentioned above?

推荐答案

你真的,真的不想直接使用用户密码作为加密密钥,尤其是使用 AES.

You really, really do not want to use a user password directly as a crypto key, especially with AES.

Rfc2898DeriveBytes 是 PBKDF2 的实现.它的作用是反复对用户密码和盐进行哈希处理.这有很多好处:

Rfc2898DeriveBytes is an implementation of PBKDF2. What it does is repeatedly hash the user password along with the salt. This has multiple benefits:

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

Firstly, you can use arbitrarily sized passwords - AES only supports specific key sizes.

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

Secondly, the addition of the salt means that you can use the same passphrase to generate multiple different keys (assuming the salt is not a constant, as it is in your example). This is important for key separation; reusing keys in different contexts is one of the most common ways cryptographic systems are broken.

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

The multiple iterations (1000 by default) slow down password guessing attacks. Consider someone who is trying to guess your AES key. If you just used the password, this would be straightforward - just try each possible password as the key. On the other hand, with PBKDF2, the attacker first has to perform 1000 hash iterations for each password guess. So while it slows down a user only slightly, it has a disproportionate effect on an attacker. (In fact it's quite common to use much higher iteration counts; 10000 is commonly recommended).

这也意味着最终的输出密钥是均匀分布的.例如,如果您使用密码,通常 128 位密钥中的 16 位将为 0(高 ASCII 位).就在那里,即使忽略密码猜测,keysearch 也会比它应该的容易 65536 倍.

It also means the final output key is uniformly distributed. If you used the password, for instance, typically 16 out of 128 bits of the key would be 0 (the high ASCII bit). That right there immediately makes keysearch 65536 times easier than it should be, even ignoring the password guessing.

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

Finally, AES has specific vulnerabilities with related key attacks. Related key attacks are possible when an attacker knows some data encrypted with several keys, and there is some known (or guessed) relation between them. For instance, if you encrypted data with both a password-key of "My AES key sucks" (16 bytes, for AES-128) and with "MY AES KEY SUCKS", a related key attack might be possible. The currently best known attacks do not actually allow breaking the full AES in this way, but they have been getting progressively better over time - just last week a new attack was published that breaks 13 rounds (out of 14 total) of AES-256 using a related key attack. It would be profoundly unwise to rely on such attacks not getting better over time.

这篇关于为什么我需要使用 Rfc2898DeriveBytes 类(在 .NET 中)而不是直接使用密码作为密钥或 IV?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

上一篇:将公钥从其他地方导入 CngKey? 下一篇:添加基于带有 SignedXml 类的 Id 属性的引用时出现“格式错误的引用元素"

相关文章