How to Resolve Java Unknownhostkey, While Using Jsch Sftp Library

How to resolve Java UnknownHostKey, while using JSch SFTP library?

You are trying to skip a host key checking by setting StrictHostKeyChecking to no.

But you have to do that before the checking, i.e. before the session.connect().


Anyway, you should never do this, unless you do not care about security. The host key checking is there to protect you from man-in-the-middle attacks.

Instead, set up an expected host key to let JSch verify it.

For example:

  • Call JSch.setKnownHosts providing a path to a .ssh/known_hosts-like file.

    To generate the .ssh/known_hosts-like file, you can use an ssh-keyscan command from OpenSSH. If you are connecting from a *nix server, you should have the command available, just run

    ssh-keyscan example.com > known_hosts

    It will have a format like:

    example.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0hVqZOvZ7yWgie9OHdTORJVI5fJJoH1yEGamAd5G3werH0z7e9ybtq1mGUeRkJtea7bzru0ISR0EZ9HIONoGYrDmI7S+BiwpDBUKjva4mAsvzzvsy6Ogy/apkxm6Kbcml8u4wjxaOw3NKzKqeBvR3pc+nQVA+SJUZq8D2XBRd4EDUFXeLzwqwen9G7gSLGB1hJkSuRtGRfOHbLUuCKNR8RV82i3JvlSnAwb3MwN0m3WGdlJA8J+5YAg4e6JgSKrsCObZK7W1R6iuyuH1zA+dtAHyDyYVHB4FnYZPL0hgz2PSb9c+iDEiFcT/lT4/dQ+kRW6DYn66lS8peS8zCJ9CSQ==

    And reference the generated known_hosts file in your JSch code.

    If you are on Windows, you can get a Windows build of ssh-keyscan from Win32-OpenSSH project or Git for Windows.

  • Call JSch.getHostKeyRepository().add() to provide the expected host key (e.g. hard-coded, as your other credentials).

    See Creating JSch HostKey instance from a public key in .pub format.

com.jcraft.jsch.JSchException: UnknownHostKey

I would either:

  1. Try to ssh from the command line and accept the public key (the host will be added to ~/.ssh/known_hosts and everything should then work fine from Jsch) -OR-
  2. Configure JSch to not use "StrictHostKeyChecking" (this introduces insecurities and should only be used for testing purposes), using the following code:

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

Option #1 (adding the host to the ~/.ssh/known_hosts file) has my preference.

JSch connection fails with UnknownHostKey even when the server's hostkey is present in the known_hosts file

Your code works for me – https://www.browxy.com/#ALIEN_137442 – It ends with "JSchException: Auth fail" – which means it gets past host key verification.

Make sure the known_hosts file is in plain ASCII encoding (or UTF-8 without BOM, which should be identical to ASCII for this kind of contents). But not UTF-8 with BOM, let alone UTF-16 or even worse.

Try also Unix line endings. Though line endings should not be an issue.

JSch: UnknownHostKey exception even when the hostkey fingerprint is present in the known_hosts file

The problem is that you have added ECDSA host key to the known_hosts, as the ssh prefers that key type:

ECDSA key fingerprint is 11:5d:55:29:8a:77:d8:08:b4:00:9b:a3:61:93:fe:e5.

But JSch prefers RSA key, which it won't find in the known_hosts:

RSA key fingerprint is 50:db:75:ba:11:2f:43:c9:ab:14:40:6d:7f:a1:ee:e3


You probably need JCE to enable ECDSA In JSch.

See JSch Algorithm negotiation fail.


Or make ssh use RSA key with -o HostKeyAlgorithms=ssh-rsa.

See How can I force SSH to give an RSA key instead of ECDSA?

You can also use ssh-keyscan:

ssh-keyscan -t rsa example.com

Query regarding com.jcraft.jsch.JSchException: UnknownHostKey: x.y.com. DSA key fingerprint is ac:ew:....

I generated the RSA keys using PuTTYgen, but every time it tries to connect it gives issue with DSA fingerprint.

It seems that you believe that the host key has something to do with key pair that you use for authentication – It does not. Those are completely unrelated. Host keys are keys of the server, they are fixed, the same for all users of the server, generated when the server is installed.

For details, see my article Understanding SSH key pairs.

I believe that once you realize this and go back to all the existing questions about UnknownHostKey, they will now make more sense to you:

  • How to resolve Java UnknownHostKey, while using JSch SFTP library?
  • com.jcraft.jsch.JSchException: UnknownHostKey


Finally I tried below approach based on one of the posts. Get the session first time with StrictHostKeyChecking as no. Once done, save the result to known hosts file on the AWS server so that next time it tries to connect to Windows server it knows it is connecting to the right server.

This works, but I think I am losing the entire reason for not setting up session.setConfig("StrictHostKeyChecking", "no") and may be it is working. What is the right way to achieve this?

It's not a perfect solution, but it's acceptable.

For a perfect solution, find out the fingerprint locally on your Windows SSH server and configure your AWS Java code to expect it upfront.



Lastly, is StrictHostKeyChecking, accept-new a more secure and recommended operation for production environments instead of no?

no is not secure at all. accept-new is as good as your above solution. But JSch does not support accept-new anyway.

(it's not difficult to implement it)

Error attempting to execute script on remote unix server using java produces

The SSH protocol (not unlike other encrypted protocols) authenticates both the client to the server and the server to the client.

The client side (your code) authenticates either with a key (which is usually preferred for an automated system) or with a username/password pair. You've got that part figured out already.

The server side (the remote system) authenticates itself with a host key, which the client can use to confirm that it's talking to the server it expects. In theory, if you are paranoid, you transfer the public key part of the host key (or at least its fingerprint) from the server to your client via some out-of-band secure mechanism. In practice, most people simply acknowledge the host key the first time they connect to the server, after which it is stored in the known_hosts file on the client. (That is, most people use a Trust On First Use policy.)

The problem arises here when you're connecting to a new server with an automated process for the first time. How can you be certain that the server you're connecting to is the one you want? If a nefarious person on the network were performing a man-in-the-middle attack on you, you would be giving that person the username and password they need to log into the real server, and your code would never be the wiser.

There are two main ways to solve this. First, you can collect the host key from the remote server manually, and then save it into the known hosts file for your automated process. This is simple as long as you can manually connect: just use a command-line SSH client to connect to the server, acknowledge the new host key at the prompt, and then copy the ~/.ssh/known_hosts file (or equivalent) from your user's home directory to the location used by your automated process.

Based on the error message, the host key you want is an RSA key (with fingerprint b6:83:60:7c:4a:98:00:ef:b9:4a:ba:b6:80:39:d6:42). Assuming that the remote Unix server is using OpenSSH or a compatible implementation, the default location for the RSA host key is /etc/ssh/ssh_host_rsa_key, although this path can be changed by directives in /etc/ssh/sshd_config. The value you want to put into the known_hosts file is the public key corresponding to this private key -- typically this would be stored in /etc/ssh/ssh_host_rsa_key.pub. Again, the easiest way to get the format right is to just connect with some other SSH client, acknowledge the host key, and then check the known_hosts file you got.

A less secure alternative would be to tell your client to simply ignore the host key, and hope for the best. (Maybe you trust your network enough that you're not worried about a man in the middle, although if you trust it that much then you probably don't need SSH either.) This is what the StrictHostKeyChecking=no setting does, which I notice is set in a comment, although misspelled.

Unknown host key with JSch

Turns out our DevOps team accidentally overrode the location of the known hosts property we were using. JSch doesn't check that the path I give for the known hosts file (and I'm assuming the private key) are valid. I'm leaving this question in case someone else ever has this issue.



Related Topics



Leave a reply



Submit