使用sshj包报错“TransportException [HOST_KEY_NOT_VERIFIABLE] Could not verify `ssh-ed25519` host key”
Posted 二木成林
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用sshj包报错“TransportException [HOST_KEY_NOT_VERIFIABLE] Could not verify `ssh-ed25519` host key”相关的知识,希望对你有一定的参考价值。
异常
使用 sshj
包远程连接服务器报错:
Exception in thread "main" net.schmizz.sshj.transport.TransportException: [HOST_KEY_NOT_VERIFIABLE] Could not verify `ssh-ed25519` host key with fingerprint `95:be:4e:db:cd:69:c3:68:b2:bc:6d:54:93:81:0a:56` for `124.75.35.139` on port 22
at net.schmizz.sshj.transport.KeyExchanger.verifyHost(KeyExchanger.java:220)
at net.schmizz.sshj.transport.KeyExchanger.handle(KeyExchanger.java:390)
at net.schmizz.sshj.transport.TransportImpl.handle(TransportImpl.java:474)
at net.schmizz.sshj.transport.Decoder.decode(Decoder.java:113)
at net.schmizz.sshj.transport.Decoder.received(Decoder.java:200)
at net.schmizz.sshj.transport.Reader.run(Reader.java:60)
错误代码
代码如下:
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.common.IOUtils;
import net.schmizz.sshj.connection.channel.direct.Session;
import net.schmizz.sshj.connection.channel.direct.Session.Command;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
public class Demo
public static void main(String[] args) throws IOException
// 创建 SSH 客户端
final SSHClient ssh = new SSHClient();
ssh.loadKnownHosts();
// 传入主机名或IP地址建立连接
ssh.connect("124.75.35.139");
Session session = null;
try
// 通过用户名和密码进行验证
ssh.authPassword("root", "root");
// 开启会话
session = ssh.startSession();
// 执行命令
final Command cmd = session.exec("ls ~");
// 获取命令的执行结果
String response = IOUtils.readFully(cmd.getInputStream()).toString();
// 打印命令的执行结果
System.out.println(response);
cmd.join(50, TimeUnit.SECONDS);
System.out.println("exit status: " + cmd.getExitStatus());
finally
try
// 关闭会话
if (session != null)
session.close();
catch (IOException e)
// Do Nothing
// 关闭连接
ssh.disconnect();
注意,其中 IP 地址、用户名和密码需要变成你自己的,其他都可以直接使用进行测试。而这里使用的 ssj
的版本如下:
<dependency>
<groupId>com.hierynomus</groupId>
<artifactId>sshj</artifactId>
<version>0.32.0</version>
</dependency>
原因
主机验证失败。
参考资料:
- net.schmizz.sshj.transport.TransportException: Could not verify ssh-ed25519 host key with fingerprint #635
- 处理“[HOST_KEY_NOT_VERIFIABLE]无法验证具有指纹的ssh-rsa主机密钥”sshj
- 在sshj中处理“[HOST_KEY_NOT_VERIFIABLE]无法验证带指纹的
ssh-rsa
主机密钥”
解决
根据查找的资料,有如下三种解决方式:
- 第一种,将报错信息中的
key
设置到addHostKeyVerifier
方法,注意在connect
方法之前。但不推荐。如ssh.addHostKeyVerifier("95:be:4e:db:cd:69:c3:68:b2:bc:6d:54:93:81:0a:56");
。 - 第二种,在
try...catch
语句中捕获该异常,从报出的异常提示信息中提取出key
,可以通过正则表达式来提取,然后将提取到的key
设置到addHostKeyVerifier
方法,即尝试了两次建立连接。 - 第三种,通过
ssh.addHostKeyVerifier(new PromiscuousVerifier());
的方式跳过主机密钥验证。
正确代码
第一种方式的代码如下, 注意 key
是我们手动从异常信息中复制粘贴出来的,如果换台远程主机连接,那么这个 key
又会不一样,所以不推荐该种方式。
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.common.IOUtils;
import net.schmizz.sshj.connection.channel.direct.Session;
import net.schmizz.sshj.connection.channel.direct.Session.Command;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
public class Demo
public static void main(String[] args) throws IOException
// 创建 SSH 客户端
final SSHClient ssh = new SSHClient();
ssh.loadKnownHosts();
// 直接设置 key
ssh.addHostKeyVerifier("95:be:4e:db:cd:69:c3:68:b2:bc:6d:54:93:81:0a:56");
// 传入主机名或IP地址建立连接
ssh.connect("124.75.35.139");
Session session = null;
try
// 通过用户名和密码进行验证
ssh.authPassword("root", "root");
// 开启会话
session = ssh.startSession();
// 执行命令
final Command cmd = session.exec("ls ~");
// 获取命令的执行结果
String response = IOUtils.readFully(cmd.getInputStream()).toString();
// 打印命令的执行结果
System.out.println(response);
cmd.join(50, TimeUnit.SECONDS);
System.out.println("exit status: " + cmd.getExitStatus());
finally
try
// 关闭会话
if (session != null)
session.close();
catch (IOException e)
// Do Nothing
// 关闭连接
ssh.disconnect();
第二种方式,通过 try...catch
捕捉到该异常后,从异常信息种自动提取 key
,然后再次发送请求建立连接。代码如下:
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.common.DisconnectReason;
import net.schmizz.sshj.common.IOUtils;
import net.schmizz.sshj.connection.channel.direct.Session;
import net.schmizz.sshj.connection.channel.direct.Session.Command;
import net.schmizz.sshj.transport.TransportException;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Demo
public static void main(String[] args) throws IOException
// 创建 SSH 客户端
SSHClient ssh = new SSHClient();
ssh.loadKnownHosts();
// 传入主机名或IP地址建立连接
try
ssh.connect("124.75.35.139");
catch (TransportException e)
// 如果抛出该异常,则自动提取 key,再次尝试建立连接
if (e.getDisconnectReason() == DisconnectReason.HOST_KEY_NOT_VERIFIABLE)
ssh = new SSHClient();
String msg = e.getMessage();
Matcher matcher = Pattern.compile("`((\\\\w2:?)16)`").matcher(msg);
if (matcher.find())
String vc = matcher.group(1);
ssh.addHostKeyVerifier(vc);
ssh.connect("124.75.35.139");
else
e.printStackTrace();
Session session = null;
try
// 通过用户名和密码进行验证
ssh.authPassword("root", "root");
// 开启会话
session = ssh.startSession();
// 执行命令
final Command cmd = session.exec("ls ~");
// 获取命令的执行结果
String response = IOUtils.readFully(cmd.getInputStream()).toString();
// 打印命令的执行结果
System.out.println(response);
cmd.join(50, TimeUnit.SECONDS);
System.out.println("exit status: " + cmd.getExitStatus());
finally
try
// 关闭会话
if (session != null)
session.close();
catch (IOException e)
// Do Nothing
// 关闭连接
ssh.disconnect();
第三种方式是直接跳过密钥验证。代码如下:
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.common.IOUtils;
import net.schmizz.sshj.connection.channel.direct.Session;
import net.schmizz.sshj.connection.channel.direct.Session.Command;
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
public class Demo
public static void main(String[] args) throws IOException
// 创建 SSH 客户端
final SSHClient ssh = new SSHClient();
ssh.loadKnownHosts();
// 跳过密钥验证
ssh.addHostKeyVerifier(new PromiscuousVerifier());
// 传入主机名或IP地址建立连接
ssh.connect("124.75.35.139");
Session session = null;
try
// 通过用户名和密码进行验证
ssh.authPassword("root", "root");
// 开启会话
session = ssh.startSession();
// 执行命令
final Command cmd = session.exec("ls ~");
// 获取命令的执行结果
String response = IOUtils.readFully(cmd.getInputStream()).toString();
// 打印命令的执行结果
System.out.println(response);
cmd.join(50, TimeUnit.SECONDS);
System.out.println("exit status: " + cmd.getExitStatus());
finally
try
// 关闭会话
if (session != null)
session.close();
catch (IOException e)
// Do Nothing
// 关闭连接
ssh.disconnect();
以上是关于使用sshj包报错“TransportException [HOST_KEY_NOT_VERIFIABLE] Could not verify `ssh-ed25519` host key”的主要内容,如果未能解决你的问题,请参考以下文章
net.schmizz.sshj.DefaultConfig Illegal key size问题,NIFI部分版本因此无法正常启动