5

我在 Java 中与RFC 3526中的一些大型组实现了Diffie–Hellman 密钥交换。我的输出是一个相当大的字节数组。将输出的前 448 位(56 字节)用于河豚密钥是否安全?我应该以任何方式转换字节,还是为密钥选择任何特定字节?

4

2 回答 2

3

从理论上讲,不,这不安全。并不是说我可以确定实际的攻击;但是 Diffie-Hellman 密钥交换的输出是由q个元素组成的组中的一个元素,最多提供sqrt(q)安全性。截断该元素的部分编码看起来不是一个好主意......

“正确”的方法是使用单向密钥派生函数。简而言之,使用良好的哈希函数(例如SHA-256 )处理 Diffie-Hellman 输出,并使用哈希结果作为键。就 Diffie-Hellman 步骤而言,散列时间可以忽略不计。Java 已经包含 SHA-256 和 SHA-512 的良好实现,如果您希望与非常旧的 Java 实现(例如 Internet Explorer 5.5 附带的 Microsoft JVM)兼容,那么您可以使用 SHA-2 的独立 Java 实现比如sphlib中的那个。或者可能从规范中重新实现它(这并不难):FIPS 180-3 (a PDF file)

如果您的密钥需要超过 128 位,那么这意味着您是 2050 年左右的时间旅行者;假设您使用适当的对称加密方案,128 位(远远)足以暂时保护您。

说到这里:不再推荐河豚了。它有 64 位块,当加密数据长度达到几千兆字节时,这意味着麻烦,现在这个大小已经不是那么大了。最好使用 128 位分组密码,例如AES。此外,在任何严肃的对称加密系统中,您都需要密钥完整性检查。这可以通过诸如HMAC之类的 MAC(消息身份验证代码)来完成,它本身构建在哈希函数之上(同样,易于实现,并且在 sphlib 中有一个 Java 实现)。或者,更好的是,在组合加密/MAC 模式下使用 AES,它将为您处理棘手的细节(因为正确使用分组密码并不容易);查找CWCGCM(两者都没有专利;后者已获得 NIST 的批准)。

于 2010-10-06T12:02:22.597 回答
0

您提出的解决方案取决于 Diffie-Hellman 交换的最重要位是否是硬核。有一些已知的小结果表明最高有效位是不可预测的,但我不知道有一篇论文足以证明你的方法是正确的。

但是,对于从 Diffie-Hellman 密钥派生密钥有几个提议。例如,一篇不错的论文是 NIST SP 800-135。到目前为止,这只是一个草稿,可以在这里找到。但是,它审查了一些现有标准。当然,使用标准总是最好自己开发。

尽管 Thomas Pornin 的提议看起来很合理,但它仍然是一个临时解决方案。为了安全起见,您可能不应该使用它。相反,我会使用已经分析过的东西(例如,TL​​S 1.2 版中使用的密钥派生方案)。

于 2010-10-13T08:56:20.420 回答