代码之家  ›  专栏  ›  技术社区  ›  Alex

com.jcraft.jsch.jscheexception:未知密钥

  •  152
  • Alex  · 技术社区  · 15 年前

    我想用 Jsch 在爪哇中建立SSH连接。我的代码产生以下异常:

    com.jcraft.jsch.JSchException: UnknownHostKey: mywebsite.com. 
    RSA key fingerprint is 22:fb:ee:fe:18:cd:aa:9a:9c:78:89:9f:b4:78:75:b4
    

    我在JSCH文档中找不到如何验证主机密钥。我在下面添加了我的代码。

    import com.jcraft.jsch.JSch;
    import com.jcraft.jsch.Session;
    
    public class ssh {
        public static void main(String[] arg) {
    
            try {
                JSch jsch = new JSch();
    
                //create SSH connection
                String host = "mywebsite.com";
                String user = "username";
                String password = "123456";
    
                Session session = jsch.getSession(user, host, 22);
                session.setPassword(password);
                session.connect();
    
            } catch(Exception e) {
                System.out.println(e);
            } 
        }
    }
    
    12 回复  |  直到 15 年前
        1
  •  197
  •   Eric Leschinski Mr. Napik    11 年前

    我也可以:

    1. 尝试 ssh 从命令行接受公钥(主机将被添加到 ~/.ssh/known_hosts 然后一切都应该在JSCH中正常工作) -或
    2. 使用以下代码将JSCH配置为不使用“stricthostkeychecking”(这会引入不安全性,应仅用于测试目的):

      java.util.Properties config = new java.util.Properties(); 
      config.put("StrictHostKeyChecking", "no");
      session.setConfig(config);
      

    选项1(将主机添加到 ~/.ssh/已知主机 文件)有我的偏好。

        2
  •  29
  •   krishnakumarp    8 年前

    避免主机密钥检查是一种安全风险。

    JSCH使用hostkeyrepository接口及其默认的实现knownhosts类来管理这一点。您可以通过实现hostkeyrepository提供允许特定密钥的备用实现。或者您可以将要允许的密钥保存在 known_hosts format 然后打电话

    jsch.setKnownHosts(knownHostsFileName);
    

    或者使用下面的公钥字符串。

    String knownHostPublicKey = "mysite.com ecdsa-sha2-nistp256 AAAAE............/3vplY";
    jsch.setKnownHosts(new ByteArrayInputStream(knownHostPublicKey.getBytes()));
    

    看见 Javadoc 了解更多详细信息。

    这将是一个更安全的解决方案。

    JSCH是开放源码的,您可以从 here . 在Examples文件夹中,查找knownhosts.java了解更多详细信息。

        3
  •  24
  •   kszatan    7 年前

    当这个问题得到一般性的回答时,我发现自己 case 即使存在 已知宿主 输入不起作用。当ssh服务器发送ecdsa指纹时会发生这种情况,因此,您将拥有如下条目:

    |1|+HASH=|HASH= ecdsa-sha2-nistp256 FINGERPRINT=
    

    问题是JSCH 偏好者 sha_rsa在连接时会尝试比较sha-rsa指纹,这会导致“未知主机”的错误。

    要解决这个问题,只需运行:

    $ ssh-keyscan -H -t rsa example.org >> known_hosts
    

    或抱怨 Jcraft 关于首选sha_rsa而不是使用本地 主机密钥算法 设置,虽然他们似乎不太 eager 修复他们 bugs .

        4
  •  16
  •   Charity Leschinski    11 年前

    根据您对ssh使用的程序,获取正确密钥的方法可能有所不同。Putty(在Windows中很流行)对ssh密钥使用自己的格式。对于我见过的Linux和BSD的大多数变体,您只需查看 ~/.ssh/known_hosts .我通常从Linux机器上进行ssh,然后将此文件复制到Windows机器上。然后我用类似的东西

    jsch.setKnownHosts("C:\\Users\\cabbott\\known_hosts");
    

    假设我把文件放在 C:\Users\cabbott 在我的Windows计算机上。如果您没有访问Linux机器的权限,请尝试 http://www.cygwin.com/

    也许其他人可以推荐其他Windows选项。我发现Putty处理ssh键的方式是将它们以非标准格式存储在注册表中,这很麻烦。

        5
  •  10
  •   Mark Beer    9 年前

    提供主机的公共RSA密钥:

    String knownHostPublicKey = "mywebsite.com ssh-rsa AAAAB3NzaC1.....XL4Jpmp/";
    
    session.setKnownHosts(new ByteArrayInputStream(knownHostPublicKey.getBytes()));
    
        6
  •  6
  •   Vishnu Prasad Kallummel    11 年前

    您还可以执行以下代码。这是测试和工作。

    import com.jcraft.jsch.Channel;
    import com.jcraft.jsch.JSch;
    import com.jcraft.jsch.JSchException;
    import com.jcraft.jsch.Session;
    import com.jcraft.jsch.UIKeyboardInteractive;
    import com.jcraft.jsch.UserInfo;
    
    public class SFTPTest {
    
        public static void main(String[] args) {
            JSch jsch = new JSch();
            Session session = null;
            try {
                session = jsch.getSession("username", "mywebsite.com", 22); //default port is 22
                UserInfo ui = new MyUserInfo();
                session.setUserInfo(ui);
                session.setPassword("123456".getBytes());
                session.connect();
                Channel channel = session.openChannel("sftp");
                channel.connect();
                System.out.println("Connected");
            } catch (JSchException e) {
                e.printStackTrace(System.out);
            } catch (Exception e){
                e.printStackTrace(System.out);
            } finally{
                session.disconnect();
                System.out.println("Disconnected");
            }
        }
    
        public static class MyUserInfo implements UserInfo, UIKeyboardInteractive {
    
            @Override
            public String getPassphrase() {
                return null;
            }
            @Override
            public String getPassword() {
                return null;
            }
            @Override
            public boolean promptPassphrase(String arg0) {
                return false;
            }
            @Override
            public boolean promptPassword(String arg0) {
                return false;
            }
            @Override
            public boolean promptYesNo(String arg0) {
                return false;
            }
            @Override
            public void showMessage(String arg0) {
            }
            @Override
            public String[] promptKeyboardInteractive(String arg0, String arg1,
                    String arg2, String[] arg3, boolean[] arg4) {
                return null;
            }
        }
    }
    

    请替换适当的值。

        7
  •  4
  •   Amaury D    9 年前

    你也可以简单地做

    session.setConfig("StrictHostKeyChecking", "no");
    

    它不安全,而且是一个不适合实时环境的解决方案,因为它将禁用全局已知的主机密钥检查。

        8
  •  1
  •   dalvarezmartinez1    11 年前

    只需替换“user”、“pass”、“sshd-ip”。并创建一个名为known_hosts.txt的文件,其中包含服务器的~/.ssh/known_hosts的内容。你会得到一个贝壳。

    public class Known_Hosts {
    public static void main(String[] arg) {
        try {
            JSch jsch = new JSch();
            jsch.setKnownHosts("known_hosts.txt");
            Session session = jsch.getSession("user", "SSHD_IP", 22);
            session.setPassword("pass");
            session.connect();
            Channel channel = session.openChannel("shell");
            channel.setInputStream(System.in);
            channel.setOutputStream(System.out);
            channel.connect();
        } catch (Exception e) {
            System.out.println(e);
        }
      }
    }
    
        9
  •  1
  •   loreii    8 年前

    我在这个愚蠢的问题上浪费了很多时间,我认为这条信息是非常正确的:“我正在访问的文件中没有主机”,但是您的系统中可以有超过一个已知主机文件(例如,我使用的是mobaxterm,它将自己的主机保存在安装目录中,从该根目录装入主机)。

    如果遇到以下情况:它在命令行中工作,但不构成应用程序,请尝试使用ssh访问远程服务器,并使用verbose-v选项检查当前使用的文件。示例如下:

     ssh -v git@gitlab.com
     OpenSSH_6.2p2, OpenSSL 1.0.1g 7 Apr 2014
     debug1: Reading configuration data /etc/ssh_config
     debug1: Connecting to gitlab.com [104.210.2.228] port 22.
     debug1: Connection established.
     debug1: identity file /home/mobaxterm/.ssh/id_rsa type 1
     debug1: identity file /home/mobaxterm/.ssh/id_rsa-cert type -1
     debug1: identity file /home/mobaxterm/.ssh/id_dsa type -1
     debug1: identity file /home/mobaxterm/.ssh/id_dsa-cert type -1
     debug1: identity file /home/mobaxterm/.ssh/id_ecdsa type -1
     debug1: identity file /home/mobaxterm/.ssh/id_ecdsa-cert type -1
     debug1: Enabling compatibility mode for protocol 2.0
     debug1: Local version string SSH-2.0-OpenSSH_6.2
     debug1: Remote protocol version 2.0, remote software version OpenSSH_7.2p2      Ubuntu-4ubuntu2.1
     debug1: match: OpenSSH_7.2p2 Ubuntu-4ubuntu2.1 pat OpenSSH*
     debug1: SSH2_MSG_KEXINIT sent
     debug1: SSH2_MSG_KEXINIT received
     debug1: kex: server->client aes128-ctr hmac-sha1-etm@openssh.com zlib@openssh.com
     debug1: kex: client->server aes128-ctr hmac-sha1-etm@openssh.com zlib@openssh.com
     debug1: sending SSH2_MSG_KEX_ECDH_INIT
     debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
     debug1: Server host key: RSA b6:03:0e:39:97:9e:d0:e7:24:ce:a3:77:3e:01:42:09
     debug1: Host 'gitlab.com' is known and matches the RSA host key.
     debug1: Found key in /home/mobaxterm/.ssh/known_hosts:19
     debug1: ssh_rsa_verify: signature correct
    

    正如您所看到的,密钥在以下位置找到:

    debug1: Found key in /home/mobaxterm/.ssh/known_hosts:19
    

    而不是在我的Windows主页上的C:\users下\ MyoLoalalSub用户 \.ssh,我只是简单地将它们合并并对齐以解决问题。

    希望以后能帮上忙

        10
  •  0
  •   Zon    11 年前

    有人能解决这个问题吗?我正在使用JSCP来使用公钥来SCP文件 身份验证(我不想使用密码身份验证)。感谢您的帮助!!!!

    这个stackoverflow条目是关于主机密钥检查的,与公钥身份验证没有关系。

    至于公钥身份验证,请尝试 following sample 使用普通(非加密)私钥,

        11
  •  0
  •   Mark Hildreth    11 年前

    设置已知主机比设置fingure打印值要好。

    当您设置已知主机时,尝试从应用程序运行的框中手动ssh(第一次,在应用程序运行之前)。

        12
  •  -1
  •   Eric Leschinski Mr. Napik    9 年前
    JSch jsch = new JSch();
    Session session = null;
    try {
    session = jsch.getSession("user", "hostname", 22); // default
    UserInfo ui = new MyUserInfo();
    session.setUserInfo(ui);
    session.setPassword("password".getBytes());
    java.util.Properties config = new java.util.Properties();
    config.put("StrictHostKeyChecking", "no");
    session.setConfig(config);
    session.connect();
    Channel channel = session.openChannel("sftp");
    channel.connect();
    System.out.println("Connected");
    } catch (JSchException e) {
    e.printStackTrace(System.out);
    } catch (Exception e) {
    e.printStackTrace(System.out);
    } finally {
    session.disconnect();
    System.out.println("Disconnected");
    }
    }