代码之家  ›  专栏  ›  技术社区  ›  Eric Lathrop

从diffie-hellman输出中选择加密密钥

  •  5
  • Eric Lathrop  · 技术社区  · 14 年前

    我实施 Diffie–Hellman key exchange 在Java中有一些大的组 RFC 3526 . 我的输出是一个相当大的字节数组。 使用输出的前448位(56字节)作为吹鱼密钥是否安全? 我应该以任何方式转换字节,还是为键选择任何特定的字节?

    2 回复  |  直到 14 年前
        1
  •  3
  •   Thomas Pornin    14 年前

    从理论上讲,不,这是不安全的。不是说我能精确定位实际的攻击;但是Diffie-Hellman密钥交换的输出是由 Q 要素和产品 平方(q) 最多安全。截断该元素的部分编码看起来不是一个好主意…

    “正确”的方法是使用单向键派生函数。简单来说,用一个好的哈希函数处理diffie-hellman输出,例如 SHA-256 并将哈希结果用作键。对于diffie-hellman步骤,散列时间可以忽略不计。Java已经包含了SHI-256和SH-512的精细实现,并且如果您与非常古老的Java实现兼容(例如,随Internet Explorer 5.5来的微软JVM),那么您可以使用独立的Java实现SHA-2,例如 sphlib . 或者可能从规范中重新实现(这并不难): FIPS 180-3 (a PDF file) .

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

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

        2
  •  0
  •   Accipitridae    14 年前

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

    然而,对于从diffie-hellman密钥派生密钥,有几个建议。 例如,一张好纸是NIST SP 800-135。到目前为止,这只是一个草案,可以找到 here . 然而,它审查了一些现有的标准。当然,使用标准总是比自己开发更好。

    虽然托马斯波宁的建议看起来合理,但它仍然是一个特别的解决方案。为了安全起见,你可能不应该使用它。相反,我会使用已经分析过的内容(例如,在TLS版本1.2中使用的密钥派生方案)。