【发布时间】:2013-08-06 10:04:14
【问题描述】:
我的印象是,基于密码的密钥派生函数的目的是每次都以相同的方式从密码生成加密安全的密钥流,因此可以依赖它们从密码生成加密密钥。
根据我在网上阅读的内容,包括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,因此输入是不同的。
【问题讨论】:
-
啊,是的,正确的填充是问题所在。常见错误,尽管在加密货币中更常见的是左填充是一个问题;将整数编码为八位字节字符串(又名字节数组)通常会导致类似的问题。如果它让你感觉更开心,我已经在常用的加密库、测试框架等中看到了这种情况。
标签: c# .net cryptography pbkdf2