4

I am just becoming familiar with encryption and the .NET framework. After looking at many examples I am seeing a repeated pattern that confuses when using the .NET Class Rfc2898DeriveBytes. When using this class to obtain an encryption key and an initialization vector the same method seems to be used.

Here is some code from an MSDN blog that demonstrates obtaining a key and an initialization vector.

byte[] salt = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 };
Rfc2898DeriveBytes pwdGen = new Rfc2898DeriveBytes("P@$$w0rd", salt, 1000);

// generate an RC2 key
byte[] key = pwdGen.GetBytes(16);
byte[] iv = pwdGen.GetBytes(8);

I have seen this used in other places also. I guess I would have thought it would be something like this ...

// generate an RC2 key
byte[] key = pwdGen.GetKey();
byte[] iv = pwdGen.GetInitializationVector();

I MUST be missing something here. If the Key and Initialization Vector (IV) are just random numbers how are they obtained again when using the proper password and salt?

webworm
  • 10,587
  • 33
  • 120
  • 217

1 Answers1

6

The RFC2898 key derivation algorithm is deterministic. When you run it with the same inputs, you'll get the same outputs.

So as long as you call GetBytes() in the same order, requesting the same number of bytes, you'll get the same key and IV.

Don't forget that in a real system the salt should be randomly generated at encryption time (and stored so that it can be retrieved at decryption time).

caf
  • 233,326
  • 40
  • 323
  • 462
  • How are the Key and IV different if they are derived from the same method? How does one know how many bytes should passed in for the parameters? – webworm Mar 25 '11 at 15:22
  • 1
    @webworm: The first `GetBytes(16)` call returns bytes 0 through 15 of the output of the algorithm, the second `GetBytes(8)` call returns bytes 16 through 23 of the output. You know how many bytes because the keysize and IV size are determined by the algorithm, cipher mode and implementation choices you've made. – caf Mar 26 '11 at 01:17
  • Does it matter if you derive the IV from the password with a random salt, or from a random password but with a constant salt? – John B Jan 30 '12 at 20:31
  • @JohnBubriski: No, but if you're going to do that then you might as well just directly use the random bytes as the IV. You must use a random salt for generating the encryption key anyway, so obtaining the IV from the next bytes of the KDF means that you do not have to separately transmit the IV. – caf Jan 30 '12 at 23:14
  • @caf If I called `PBKDF2` with an iteration count of 1000 (guessing here) obtaining 24 bytes and took bytes 0-15 as the key and bytes 16-23 as the iv would that be the same as using `Rfc2898DeriveBytes` and than calling `GetBytes(16) for the key ` followed by `GetBytes(8)` for the iv? – zaph May 16 '14 at 16:15
  • I wonder why the docs say that this method produces different keys on each call. This is obviously wrong: https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.rfc2898derivebytes.getbytes?f1url=https%3A%2F%2Fmsdn.microsoft.com%2Fquery%2Fdev15.query%3FappId%3DDev15IDEF1%26l%3DEN-US%26k%3Dk(System.Security.Cryptography.Rfc2898DeriveBytes.GetBytes)%3Bk(vs.tfs.vctrl.DiffMerge.Legend)%3Bk(SolutionItemsProject)%3Bk(TargetFrameworkMoniker-.NETFramework%2CVersion%3Dv4.6)%3Bk(DevLang-csharp)%26rd%3Dtrue&view=netframework-4.7.2#remarks – user2173353 Jan 07 '19 at 13:43
  • @user2173353: What that's saying is that subsequent `.GetBytes()` calls to the same `Rfc2898DeriveBytes` object don't keep giving you the same data. – caf Jan 08 '19 at 09:44