我在Java中使用Diffie–Hellman key exchange中的一些大型组实现了RFC 3526。我的输出是一个相当大的字节数组。 使用输入键的输出的前448位(56字节)是否安全?我应该以任何方式转换字节,还是选择键的任何特定字节?
答案 0 :(得分: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位(足够)足以保护您的暂时性。
说到:不再推荐Blowfish了。它有64位块,这意味着当加密数据长度达到几千兆字节时会遇到麻烦,这个大小现在还不是很大。最好使用128位分组密码,例如AES。此外,在任何严肃的对称加密系统中,您都需要进行密钥完整性检查。这可以通过MAC(消息认证码)来完成,例如HMAC,它本身构建在一个散列函数上(然后再次,易于实现,并且在sphlib中有一个Java实现)。或者,更好的是,在组合加密/ MAC模式下使用AES,它将为您处理棘手的细节(因为正确使用分组密码不容易);查询CWC和GCM(两者均无专利;后者已获得NIST批准)。
答案 1 :(得分:0)
你提出的解决方案取决于Diffie-Hellman交换的最重要部分是否是硬核。已知有一些小的结果表明最重要的部分是不可预测的,但我不知道一篇足够强大的论文表明你的方法是正确的。
然而,有几个关于Diffie-Hellman密钥的密钥推导的提议。 例如。一篇好文章是NIST SP 800-135。到目前为止,这只是一个草案,可以找到here。但是,它审查了一些现有标准。当然,使用标准总是比自己开发更好。
虽然Thomas Pornin的提案看起来很合理,但它仍然是一个临时解决方案。为了安全起见,你可能不应该使用它。相反,我会使用已经分析过的东西(例如在TLS版本1.2中使用的密钥派生方案)。