3

I was under the impression that the point of password based key-derivation functions was to generate a cryptographically secure key stream from a password in the same way every time, so they can be relied upon for producing encryption keys from passwords.

From what I've read online, including stack overflow, this seems to be the intended use.

So when I was generating different outputs for what I thought were the same inputs I assumed I was using it wrong. To test this, I wrote a test case for Rfc2898DeriveBytes that uses it in the way the documentation suggests.

[TestMethod]
public void PBKDF2_Works() {
    var salt = new byte[] { 0x01, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0D, 0x15 };
    var password = "password";
    var iterations = 1000;
    var len = 48;

    var gen1 = new Rfc2898DeriveBytes(password, salt, iterations);
    var gen2 = new Rfc2898DeriveBytes(password, salt, iterations);

    var bytes1 = gen1.GetBytes(len);
    var bytes2 = gen2.GetBytes(len);
    Assert.AreEqual(bytes1, bytes2);
}

This test case is failing, and I can't figure out why. Am I mis-using the function, or am I misunderstanding what it should be used for?

Edit: Ok, the test method above was a flawed test because I wasn't using the Collection form of the assertion. I thought that AreEqual would call .Equals on arguments, and that for collections that would be implemented to compare contents.

The problem I was having was that I thought the same arguments to Rfc2898DeriveBytes was producing different output for the same input, but the input was subtly different:

I generated a 16 byte salt and stored it in the database, but because of the field length, when the salt was retrieved for decryption, the first 16 bytes were the same (so I thought it was using the same information) but these were followed by another 48 bytes of 0s, and the inputs were therefore different.

Community
  • 1
  • 1
danpalmer
  • 2,163
  • 4
  • 24
  • 41
  • Ah, yes, right padding being the issue. Common mistake, although in crypto it is more common that left padding is an issue; the encoding of an integer to octet string (aka byte array) is often leading to similar issues. If it makes you feel more happy, I've seen this happen in commonly used crypto libraries, test frameworks etc.. – Maarten Bodewes Aug 06 '13 at 12:33

1 Answers1

3

MSTest's Assert.AreEqual will normally do reference equality comparison on collections (unless it is a custom collection that overrides Equals), which is not usually what you want. Try using CollectionAssert.AreEqual.

Mike Zboray
  • 39,828
  • 3
  • 90
  • 122
  • Ok, that was a stupid mistake, I'll edit the question to more closely reflect the real code where I'm having the issue later. Thanks. – danpalmer Aug 05 '13 at 16:09
  • Marking this as the answer, because it answers the immediate question asked and is useful to know in general. Read the edit for the full explanation of what the issue was. – danpalmer Aug 06 '13 at 08:23