首页 文章

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

提问于
浏览
3

我正在使用JSCH 0.1.53连接到远程SSH服务器,该服务器使用1024位RSA密钥 . 当我们也使用1024位RSA密钥时,我们能够成功连接到远程服务器,但是当我们生成更强大的2048位密钥时,我们就无法连接了 . 我们收到一条错误消息,上面写着“主要大小必须是64的倍数,并且只能在512到2048之间”,并且来自对DHGEX.java(Diffie-Hellman Group EXchange)的调用 .

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

由于我们的一切看起来很好,我开始在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天不同的模数值,并且它们在基础64或基数10中编码时仅与最后几个字符不同 . 模数值被重用,有时只有一次,有时十几次,但有很多不同的值,所以键既不是一次性使用也不生成一次并永久重用 .

这是(让服务器发送许多不同的密钥,在数字上非常接近,有一些重用但许多唯一值)在任何条件下的预期行为,尤其是当客户端使用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/

UPDATE:

在进一步阅读之后,我相信Diffie-Hellman的前向保密特征意味着不同的素数(通常来自存储在/ etc / ssl / moduli之类的预先生成的集合)将用于每个会话(源:https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange#Forward_secrecy)和那个素数used实际上并不是RSA密钥(来源:https://stackoverflow.com/a/23346185/1247705),所以看到许多不同的p值不再是一个问题 . 我'm still surprised that they'的 Value 如此接近,但也许这也是预期的 .

远端是使用Solaris SSH 1.1.4(据我所知它基于OpenSSH)作为SSH守护进程 . 是否期望该守护进程通过2047位素数作为Diffie-Hellman密钥交换的一部分,有没有什么可以让它发送2048位素数而不是?

2 回答

  • 1

    我们修复了类似的症状:

    Security.insertProviderAt(new BouncyCastleProvider(), 1)
    

    我们使用Jsch 0.1.54并看到:

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

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

  • 4

    我最终通过禁用使用Diffie-Hellman组密钥交换变体的密钥交换算法解决了这个问题 . @Brian Low似乎通过使用BouncyCastle而不是JDK的内置安全提供程序来解决它 .

    我认为这些都是解决潜在问题的解决方法(这似乎是JDK中他们接受的密钥大小或OpenSSH中他们生成的密钥大小的错误),但我和我的项目都没有足够关心花费时间和金钱试图强迫一方或另一方掌握问题的所有权 .

相关问题