Jsch 0.1.67公私钥SSH认证失败,原生SSH可正常连接如何解决?
Jsch 0.1.67 公钥指纹不匹配问题解决方案
根因定位
Jsch 0.1.67版本存在两个已知的公钥处理异常场景,会直接导致发送到服务端的公钥和本地实际公钥不符:
- 默认优先对RSA密钥使用SHA-256指纹算法,如果远端sshd版本较低默认仅支持SHA1指纹的RSA签名,Jsch发送的公钥签名格式会和远端
authorized_keys中存储的公钥格式不匹配 - 若你生成的是OpenSSH新格式私钥(即文件头为
-----BEGIN OPENSSH PRIVATE KEY-----而非传统PEM格式的-----BEGIN RSA PRIVATE KEY-----),Jsch 0.1.67对新格式私钥的公钥推导逻辑存在bug,即使你显式传入公钥文件,Jsch内部仍会错误从私钥推导公钥,导致发送的公钥内容错误
可行解决方案步骤
第一步:确认并修复私钥格式兼容性
执行命令查看私钥文件头:head -n1 ~/.ssh/id_rsa
如果输出为-----BEGIN OPENSSH PRIVATE KEY-----,需要重新生成传统PEM格式的密钥,执行命令:ssh-keygen -t rsa -m PEM -f ~/.ssh/id_rsa
生成后重新执行ssh-copy-id ftpuser@192.168.56.99同步公钥到远端,先确认原生SSH命令仍可正常连接。
第二步:显式指定Jsch公钥签名算法
Jsch 0.1.67默认开启的rsa-sha2-256/512签名算法低版本sshd无法识别,会将收到的公钥判定为不匹配,你需要在获取Session前手动指定优先使用ssh-rsa签名算法:
JSch jsch = new JSch(); // 加载密钥,第三个参数为私钥密码,无密码传null即可 jsch.addIdentity("~/.ssh/id_rsa", "~/.ssh/id_rsa.pub", null); Session session = jsch.getSession("ftpuser", "192.168.56.99", 22); // 配置兼容的签名算法 java.util.Properties config = new java.util.Properties(); config.put("server_host_key", "ssh-rsa"); config.put("PubkeyAcceptedAlgorithms", "ssh-rsa"); session.setConfig(config); // 生产环境建议保留HostKey校验逻辑,此处仅为测试简化 session.setConfig("StrictHostKeyChecking", "no"); session.connect();
第三步:优化密钥加载逻辑(可选)
如果第二步仍未解决,可跳过传入公钥参数,让Jsch直接从传统PEM格式私钥推导公钥,避免Jsch内部加载顺序bug覆盖正确公钥:jsch.addIdentity("~/.ssh/id_rsa", null, null);
第四步:版本升级备选
如果业务允许依赖升级,可直接升级到Jsch 0.1.68+版本,官方已修复OpenSSH格式私钥的公钥推导bug;也可降级到Jsch 0.1.54及以下版本,该版本默认未开启rsa-sha2扩展,兼容性更高。
内容的提问来源于stack exchange,提问作者Dave Breeze
相关产品推荐
相关产品推荐

