81

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

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

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

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

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 属性。

IE。

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

'rj' 应该准备好了!

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

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

4

1 回答 1

197

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

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

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.

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).

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.

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.

于 2010-05-07T18:16:31.167 回答