DHGEX 在 Java 8 下使用 2048 位密钥失败,但使用 1024 位密钥成功

Tim*_*Tim 4 java jsch public-key-encryption diffie-hellman

我使用 JSCH 0.1.53 连接到使用 1024 位 RSA 密钥的远程 SSH 服务器。当我们还使用 1024 位 RSA 密钥时,我们能够成功连接到远程服务器,但是当我们生成更强的 2048 位密钥时,我们就无法连接了。我们收到一条错误消息,内容为“素数大小必须是 64 的倍数,并且范围只能从 512 到 2048”,并且源自对 DHGEX.java (Diffie-Hellman Group EXchange) 的调用。

我们正在运行 Java 1.8,并且错误消息正确指定了 2048 的最大位大小,所以问题不在于 Java 1.6 和 1.7 中 1024 位的 JCE 密钥限制。我们已经通过 openssl rsa -text -noout -in id_rsa 和 ssh-keygen -lf id_rsa.pub 确认我们的私钥和公钥实际上都是 2048 位。

由于一切看起来都很好,我开始在 JSCH 代码中添加调试行并重新编译 JAR,我最终能够确定在密钥交换期间传递给我们的模数实际上是 2047 位长。现在,2047 位的长度本质上并不意味着您没有生成 2048 位的密钥,或者它的强度不如实际包含 2048 位的密钥,它只是意味着您碰巧得到了相乘的两个素数到第一位是 0 的东西。所以这是预期的行为(有时),JCE 检查可能应该是 (n % 64 == 0 || n % 64 == 63)。但是 JCE 在这一点上是一个坚持者,因此它拒绝了这个密钥,因为它不是它认为有效的长度。

基于此,我以为我发现了问题:远程服务器生成了一个仅包含 2047 位的 2048 位密钥,因此他们只需要生成一个新密钥(并继续这样做,直到他们得到一个真正合适的密钥) 2048 位)。但是当我询问他们的管理员时,他们坚持认为他们使用的是 1024 位密钥,而这确实是您通过 SSH 连接时在 known_hosts 文件中获得的内容。所以这毕竟不是原因。

所以我开始记录缓冲区的内容,其中包含他们发送给我们的内容并提取 p 和 g 值(模数和组),我发现在短短几天的测试中,有 33不同的模数值,并且当以 base 64 或 base 10 编码时,所有这些值仅在最后几个字符上有所不同。 Modulii 值被重用,有时只有一次,有时是十几次,但有很多不同的值,所以键既不是一次性生成的,也不是生成一次就可以永远重复使用的。

这是(让服务器发送许多在数字上非常接近的不同密钥,有一些重用但有许多唯一值)在任何条件下的预期行为,尤其是当客户端使用 2048 位密钥但服务器使用1024 位密钥?除了自上周开始调查以来我所阅读的内容之外,我对 Diffie-Hellman 组交换一无所知,所以也许这就是它的工作原理,但对我来说似乎很奇怪。

此外,SSH 标准是否指定了在此类情况下应如何生成密钥的任何内容?我还没有发现远端使用的是什么 SSH 服务器(我怀疑是 OpenSSH,但不确定也不知道是什么版本),但我希望可能有一些标准来强制使用与请求大小相同的密钥(在 1^(n-1) 和 1^n - 1 之间),并且远程服务器可能可以选择强制执行此操作,或者我可以针对它们提交错误让他们改变行为。我可能还会提交一个针对 JDK 的错误,以允许 n-1 位的键,第一位为 0 填充。

任何人都可以提供的任何指导将不胜感激。

我也将此问题发布到 JSCH 邮件列表:https ://sourceforge.net/p/jsch/mailman/message/35042955/

更新:

进一步阅读后,我相信 Diffie-Hellman 的前向保密特性意味着每个会话都将使用不同的素数(通常来自存储在 /etc/ssl/moduli 之类的预先生成的集合)(来源:https://en。 wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange#Forward_secrecy),并且使用的素数实际上并不是 RSA 密钥(来源:https : //stackoverflow.com/a/23346185/1247705),所以事实上很多看到不同的 p 值似乎不再是一个问题。我仍然对它们的价值如此接近感到惊讶,但也许这也是意料之中的。

另一边是使用 Solaris SSH 1.1.4(据我所知它基于 OpenSSH)作为 SSH 守护进程。作为 Diffie-Hellman 密钥交换的一部分,该守护进程是否会传递 2047 位素数,是否有什么办法可以让它发送 2048 位素数?

Bri*_*Low 5

我们修复了类似的症状:

Security.insertProviderAt(new BouncyCastleProvider(), 1)
Run Code Online (Sandbox Code Playgroud)

我们正在使用 Jsch 0.1.54 并看到:

java.security.InvalidAlgorithmParameterException: DH 密钥大小必须是 64 的倍数,并且范围只能从 512 到 4096(含)。不支持特定的密钥大小 2047

可能相关的是JDK-8164963: InvalidAlgorithmParameterException prime size issue after JDK upgrade with JSCH libraries