1

I need to create a .netstandard2.0 C# library that derives a symmetric key from a password. Therefore, I cannot use many of new, fancy classes that Microsoft provides, and need to stick with PasswordDeriveBytes.

My PoC quite followed the one in the documentation:

// use .netstandard2.0 kdf to derive the key
int kdfIterations = 10000;

// some random values
var salt = new byte[] { 18, 25, 36, 78, 96, 174, 56, 96, 47, 12, 13, 14, 47, 47, 36, 49 };
var iv = new byte[] { 17, 6, 9, 53, 207, 8, 0, 16, 47, 89, 44, 22, 33, 44, 77, 15 };

byte[] key = iv;
var passwordDeriveBytes = new PasswordDeriveBytes("mySuperSecretPassword", salt);
for (int i = 0; i < kdfIterations; i++)
{   
    key = passwordDeriveBytes.CryptDeriveKey("TripleDES", "SHA256", 192, key.Take(8).ToArray());
}

But as a matter of fact I have revealed that when I swap salt and iv, the derived key value stays the same. Bummer. This answer provides an explanation that salt is not used indeed. But when you play with it, you realize that iv value to the CryptDeriveKey() actually does not matter either, whatever the number of kdfIterations, the result does not change. In other words, derived key only depends on the password itself. That seems like very crappy implementation indeed. Is that true or am I missing something?

I can come up with a workaround like

// use .netstandard2.0 kdf to derive the key
int kdfIterations = 10000;

// some random values
var salt = new byte[] { 18, 25, 36, 78, 96, 174, 56, 96, 47, 12, 13, 14, 47, 47, 36, 49 };
var iv = new byte[] { 17, 6, 9, 53, 207, 8, 0, 16, 47, 89, 44, 22, 33, 44, 77, 15 };

byte[] key = iv;
for (int i = 0; i < kdfIterations; i++)
{   
    using var passwordDeriveBytes = new PasswordDeriveBytes($"{Convert.ToBase64String(key)}mySuperSecretPassword{Convert.ToBase64String(salt)}", salt);
    key = passwordDeriveBytes.CryptDeriveKey("TripleDES", "SHA256", 192, key.Take(8).ToArray());
}

which already takes salt, iv and kdfIterations into account, but I believe the documentation should actually warn that iv and salt are there just showcasing. Which is incredible for me, as I majored in cryptography.

zajic
  • 135
  • 8
  • 1
    `PasswordDeriveBytes` supports two logics, one is an MS extended (proprietary) implementation of the PBKDF1 algorithm, the other is a wrapper around CAPI's `CryptDeriveKey()` function. The first conciders salt and iteration count, the latter not (and seemingly also not the IV), see [here](https://learn.microsoft.com/de-de/archive/blogs/shawnfa/generating-a-key-from-a-password#cryptderivekey) and also [this post](https://stackoverflow.com/a/71284660/9014097). – Topaco May 05 '22 at 09:42

0 Answers0