我的印象是,基于密码的密钥派生函数的重点是每次都以相同的方式从密码生成加密安全的密钥流,因此可以依赖它们从密码生成加密密钥。
根据我在网上阅读的内容,包括stack overflow,这似乎是预期用途。
因此,当我为我认为相同的输入生成不同的输出时,我认为我用错了。为了测试这一点,我编写了一个测试用例Rfc2898DeriveBytes
,按照文档建议的方式使用它。
[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);
}
这个测试用例失败了,我不知道为什么。我是误用了这个功能,还是我误解了它的用途?
编辑:好的,上面的测试方法是一个有缺陷的测试,因为我没有使用断言的集合形式。我认为 AreEqual 会在参数上调用 .Equals,而对于将被实现以比较内容的集合。
我遇到的问题是我认为 Rfc2898DeriveBytes 的相同参数会为相同的输入产生不同的输出,但输入略有不同:
我生成了一个 16 字节的 salt 并将其存储在数据库中,但是由于字段长度的原因,当检索 salt 进行解密时,前 16 个字节是相同的(所以我认为它使用了相同的信息)但是这些被遵循另外 48 个字节的 0,因此输入不同。