基于 PBKDF2 的 System.Cryptology.RFC2898DeriveBytes() 对于 Unicode 密码散列是否比传统方法“更好”?

信息安全 密码学 密码 哈希 。网
2021-08-31 03:36:36

什么时候使用RFC2898DeriveBytes与典型的散列比较合适?

更新

我现在了解 KDF 通常用于创建对称密钥,以便可能用于加密流。我现在也明白 PBKDF2 已经过时PasswordDeriveBytes这个问题的目的是探索重新利用 KDF 作为存储散列密码的强大方法的可能性。我打算加密的内容是人类可以记住并输入计算机的 Unicode 字符串。

我对 KDF 感兴趣的原因是因为它是

  1. 创建彩虹表的速度很慢,因此计算成本很高
  2. .NET 中的基础库已获得 FIPS 批准,如果我们使用 SHA-256 ,则可以将此 KDF 与NIST 建议一起使用

问题

与普通散列方法相反,支持/反对以这种方式使用 KDF 的论点是什么?(免责声明:什么正常的散列方法?)

4个回答

PasswordDeriveBytes实现 PBKDF1 密钥派生功能。KDF 是将一段秘密数据(这里是“密码”,即适合人类大脑并可以用人类手指输入的数据)转换为足以满足算法需要的比特序列的函数。对称密钥(例如对称加密)。KDF 不适用于其他任何东西,尤其是密码存储。

散列函数可以用作 KDF,前提是您需要的对称密钥不超过散列函数输出大小。但是,这样的 KDF 将非常粗糙。好的 KDF 应该提供的一个特性是足够慢这是因为“密码”本质上容易受到穷举搜索的影响(也称为“字典攻击”:用户倾向于选择简单的单词或组合作为密码,只需几百万或数十亿次尝试就可以猜到)。在给定的系统中,通常可以容忍相对较慢的 KDF:尝试进行身份验证的用户不会看到密钥派生函数的 1µs 和 1ms 延迟之间的差异;但是 1000 倍的减速对攻击者来说是致命的:

PBKDF1 包含一个“迭代计数”,这是一个专门用于此目的的参数:以可配置的方式使密钥派生足够慢。一个简单的哈希函数太快了。作为 KDF 的使用正是您更喜欢 PBKDF1 而不是散列函数的地方。实际上,不推荐使用 PBKDF1;来自相同标准的 PBKDF2应该更健壮。

哈希函数是比 KDF 更通用的对象,并且有许多 KDF 不满足的其他用途。

你想要做什么还不清楚:你使用术语“签名”,这通常意味着“非对称数字签名”,就像 RSA 或 ECDSA 一样;有些人倾向于使用术语“签名”来指定对称完整性检查,例如MAC(称其为“签名”是不恰当的,但很普遍)。但是,这在某些时候需要一些秘密,一个密钥,而哈希函数是无密钥的。

NIST在散列和存储密码时批准 PBKDF2,但这不是其最初的预期目的。值得注意的是,StackExchange 也将 PBKDF2用于相同目的。 源代码可在此处获得。

有关BCrypt 和 PBKDF2 之间的比较,请参阅此答案。BCrypt 是更传统的密码存储方法。

我正在考虑 PBKDF2,因为它内置于 .NET 中并且已经符合 FIPS。

除非我遗漏了什么,否则 PasswordDeriveBytes - 和其他 PBKDF 实现 - 不用于存储密码,也不能用来代替“典型”哈希。

它的目的是根据用户提供的密码创建用于对称加密的加密密钥。

为了澄清,请考虑以下情况:
您有一个需要加密文件的应用程序。这是由用户自行决定的,并且可以根据他的选择进行解密。
哦,假设 MS Word 具有加密其内容的功能。或加密的 ZIP 文件。
您想为用户提供访问它的控制权,但又不想依赖用户生成一个强大的、随机的、精确 256 位的密钥,这会使其难以记住等。
所以,您允许用户设置他想要的任何密码 - 并从中派生加密密钥。

您绝不会存储密码,或者使用简单的哈希来存储它。它仅用于创建密钥材料。

PBKDF2 优于10 年前在RFC 2898中弃用的 PBKDF1。它在Rfc2898DeriveBytes 类 (System.Security.Cryptography)中为 .NET 实现

我也很高兴看到从 Java 6 开始,在 SunJCE 中有一个 PBKDF2 的实现:PBKDF2WithHmacSHA1。

对于早期版本的 Java,如BlackBerry App Security - Stack Overflow中所述,PBKDF2 的实现位于A free Java implementation of RFC 2898 / PKCS#5 PBKDF2

不过,我想知道,如果使用 SHA-256 会比现在已弃用的 SHA-1 更好。