You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中使用OPENSSH IdentityFile连接SFTP失败的问题排查

解决JSch兼容OpenSSH密钥及RSA认证失败问题

问题背景

开发Java SFTP应用,需兼容两种认证方式:测试环境用密码认证,生产环境用标准id_rsa OpenSSH密钥认证。目前密码连接正常,但密钥连接出现两类错误:

  • 使用OpenSSH格式私钥时,jsch.addIdentity(identityFile)报错invalid privatekey: [B@48c76607
  • 使用RSA格式私钥时,jschSession.connect()报错com.jcraft.jsch.SftpException: Auth fail

当前实现代码:

JSch jsch = new JSch();
jsch.setKnownHosts(knownHosts);

if (!identityFile.equals("")) {
    jsch.addIdentity(identityFile, passphrase);
}
Session jschSession = jsch.getSession(user, host, port);
jschSession.setConfig("StrictHostKeyChecking", "no");

if (identityFile.equals("")) {
    jschSession.setPassword(pass);
    jschSession.setConfig("PreferredAuthentications", "password");
} else {
    jschSession.setConfig("PreferredAuthentications", "publickey");
}
jschSession.connect();
ChannelSftp channelSftp = (ChannelSftp) jschSession.openChannel("sftp");
channelSftp.connect();

环境信息:

  • JSch版本:jsch-0.1.55.jar
  • Java版本:Java 8
  • 服务器:OpenSSH_8.9p1 Ubuntu-3ubuntu0.3
  • 密钥权限配置正确,Shell/FileZilla用密钥连接正常,但Java无法连接

RSA密钥连接时JSch日志:

Connecting to <HOST> port <PORT>
Connection established
Remote version string: SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.3
Local version string: SSH-2.0-JSCH-0.1.54
CheckCiphers: aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,3des-ctr,arcfour,arcfour128,arcfour256
CheckKexes: diffie-hellman-group14-sha1,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521
CheckSignatures: ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521
SSH_MSG_KEXINIT sent
SSH_MSG_KEXINIT received
kex: server: curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,sntrup761x25519-sha512@openssh.com,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256
kex: server: rsa-sha2-512,rsa-sha2-256,ecdsa-sha2-nistp256,ssh-ed25519
kex: server: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com
kex: server: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com
kex: server: umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1
kex: server: umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1
kex: server: none,zlib@openssh.com
kex: server: none,zlib@openssh.com
kex: server: 
kex: server: 
kex: client: ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1
kex: client: ssh-rsa,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521
kex: client: aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc,aes192-ctr,aes192-cbc,aes256-ctr,aes256-cbc
kex: client: aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc,aes192-ctr,aes192-cbc,aes256-ctr,aes256-cbc
kex: client: hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96
kex: client: hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96
kex: client: none
kex: client: none
kex: client: 
kex: client: 
kex: server->client aes128-ctr hmac-sha1 none
kex: client->server aes128-ctr hmac-sha1 none
SSH_MSG_KEX_ECDH_INIT sent
expecting SSH_MSG_KEX_ECDH_REPLY
Host '<HOST>' is known and matches the ECDSA host key
SSH_MSG_NEWKEYS sent
SSH_MSG_NEWKEYS received
SSH_MSG_SERVICE_REQUEST sent
SSH_MSG_SERVICE_ACCEPT received
Authentications that can continue: publickey
Next authentication method: publickey
Disconnecting from <HOST> port <PORT>

解决方案

1. 处理OpenSSH密钥格式不兼容问题

JSch 0.1.55不支持开头为-----BEGIN OPENSSH PRIVATE KEY-----的密钥格式,需将其转换为传统RSA格式:

ssh-keygen -p -f id_rsa -m pem -P "" -N ""

参数说明:

  • -p:修改私钥密码
  • -f id_rsa:指定目标私钥文件
  • -m pem:转换为PEM格式(传统RSA格式)
  • -P "":原密码为空(若有密码替换为实际值)
  • -N "":新密码为空(若需设置密码替换为实际值)

转换后私钥开头为-----BEGIN RSA PRIVATE KEY-----,即可被JSch识别。

2. 修复RSA密钥认证失败问题

从日志可见,服务器支持的签名算法为rsa-sha2-512,rsa-sha2-256,但JSch默认未启用这些算法,需手动添加配置:
修改代码中密钥认证分支的配置:

if (!identityFile.isEmpty()) {
    jsch.addIdentity(identityFile, passphrase);
    // 启用RSA SHA2系列签名算法
    jschSession.setConfig("PubkeyAcceptedKeyTypes", "+ssh-rsa,rsa-sha2-256,rsa-sha2-512");
    jschSession.setConfig("PreferredAuthentications", "publickey");
}

注意:确保使用JSch 0.1.55版本(该版本首次支持rsa-sha2算法,0.1.54及以下版本不支持)。

3. 优化代码逻辑

简化重复的identityFile判断逻辑:

JSch jsch = new JSch();
jsch.setKnownHosts(knownHosts);

Session jschSession = jsch.getSession(user, host, port);
jschSession.setConfig("StrictHostKeyChecking", "no");

if (!identityFile.isEmpty()) {
    jsch.addIdentity(identityFile, passphrase);
    jschSession.setConfig("PubkeyAcceptedKeyTypes", "+ssh-rsa,rsa-sha2-256,rsa-sha2-512");
    jschSession.setConfig("PreferredAuthentications", "publickey");
} else {
    jschSession.setPassword(pass);
    jschSession.setConfig("PreferredAuthentications", "password");
}

jschSession.connect();
ChannelSftp channelSftp = (ChannelSftp) jschSession.openChannel("sftp");
channelSftp.connect();

4. 额外检查项

  • 确认服务器sshd_config中已开启PubkeyAuthentication yes
  • 确认用户家目录下的.ssh/authorized_keys文件权限为600,.ssh目录权限为700
  • 确认authorized_keys中已添加对应私钥的公钥内容

内容的提问来源于stack exchange,提问作者Marco Frag Delle Monache

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 18:25:02