Dealing with "[HOST_KEY_NOT_VERIFIABLE] Could not verify `ssh-rsa` host key with fingerprint" in sshj

27.2k views Asked by At

I having a strange issue with sshj (am using sshj v0.6.0) for which I would need some help from someone. Authentication with public key works fine on some machines but doesnt work fine on other machines and I see the below error.

The only difference that I could make out was that the UNIX ID in question viz coonradt seems to have the below listed configuration setup under ~/.ssh/config only on the box on which the below errors are being triggered

Host *
    Protocol 1,2
    FallBackToRsh no
    ForwardAgent yes
    ForwardX11 yes
    PasswordAuthentication yes
    RhostsAuthentication no
    RhostsRSAAuthentication no
    RSAAuthentication yes
    NoHostAuthenticationForLocalhost yes
    StrictHostKeyChecking no
  KeepAlive yes

From the above config file I learnt that the ID in question is supposed to make use of Protocol 1,2 and I suspect that this might have something to do with my failures (I am not very sure about it, but this is just a hunch)

For all other UNIX IDs for which this works fine, I dont have any such config file.

PS : I cannot alter the config of the UNIX ID "coonradt" since this ID is being used by the central hudson servers.

Would appreciate if someone could please help me suggest as to what might be wrong here

Following is the error that I am seeing :

Oct 24, 2011 2:30:37 AM net.schmizz.sshj.DefaultConfig initCipherFactories
WARNING: Disabling high-strength ciphers: cipher strengths apparently limited by JCE policy
Oct 24, 2011 2:30:38 AM net.schmizz.sshj.transport.TransportImpl init
INFO: Client identity string: SSH-2.0-SSHJ_0_6_0
Oct 24, 2011 2:30:38 AM net.schmizz.sshj.transport.TransportImpl init
INFO: Server identity string: SSH-1.99-OpenSSH_4.3
Oct 24, 2011 2:30:38 AM net.schmizz.sshj.transport.KeyExchanger sendKexInit
INFO: Sending SSH_MSG_KEXINIT
Oct 24, 2011 2:30:38 AM net.schmizz.sshj.transport.KeyExchanger handle
INFO: Received SSH_MSG_KEXINIT
Oct 24, 2011 2:30:38 AM net.schmizz.sshj.transport.kex.AbstractDHG init
INFO: Sending SSH_MSG_KEXDH_INIT
Oct 24, 2011 2:30:38 AM net.schmizz.sshj.transport.KeyExchanger handle
INFO: Received kex followup data
Oct 24, 2011 2:30:38 AM net.schmizz.sshj.transport.kex.AbstractDHG next
INFO: Received SSH_MSG_KEXDH_REPLY
Oct 24, 2011 2:30:38 AM net.schmizz.sshj.transport.TransportImpl die
SEVERE: Dying because - net.schmizz.sshj.transport.TransportException: [HOST_KEY_NOT_VERIFIABLE] Could not verify `ssh-rsa` host key with fingerprint `ca:0b:b3:7f:53:5a:e3:bc:bf:44:63:d8:2d:26:c0:41` for `mymachine.domain.com` on port 22
Oct 24, 2011 2:30:38 AM net.schmizz.concurrent.Promise tryRetrieve
SEVERE: <<kex done>> woke to: net.schmizz.sshj.transport.TransportException: [HOST_KEY_NOT_VERIFIABLE] Could not verify `ssh-rsa` host key with fingerprint `ca:0b:b3:7f:53:5a:e3:bc:bf:44:63:d8:2d:26:c0:41` for `mymachine.domain.com` on port 22
Oct 24, 2011 2:30:38 AM net.schmizz.sshj.transport.TransportImpl setService
INFO: Setting active service to null-service
Oct 24, 2011 2:30:38 AM com.test.jaws.execution.ssh.impl.SSHJClientImpl$ExceptionHandler handleSevereCondition
SEVERE: mymachine.domain.com is not added to your /x/home/coonradt/.ssh/known_hosts file. 
Throwable occurred: net.schmizz.sshj.transport.TransportException: [HOST_KEY_NOT_VERIFIABLE] Could not verify `ssh-rsa` host key with fingerprint `ca:0b:b3:7f:53:5a:e3:bc:bf:44:63:d8:2d:26:c0:41` for `mymachine.domain.com` on port 22
    at net.schmizz.sshj.transport.KeyExchanger.verifyHost(KeyExchanger.java:222)
    at net.schmizz.sshj.transport.KeyExchanger.handle(KeyExchanger.java:373)
    at net.schmizz.sshj.transport.TransportImpl.handle(TransportImpl.java:477)
    at net.schmizz.sshj.transport.Decoder.decode(Decoder.java:127)
    at net.schmizz.sshj.transport.Decoder.received(Decoder.java:195)
    at net.schmizz.sshj.transport.Reader.run(Reader.java:72)
5

There are 5 answers

4
shikhar On

How about adding a HostKeyVerifier for this machine?

sshClient.addHostKeyVerifier("ca:0b:b3:7f:53:5a:e3:bc:bf:44:63:d8:2d:26:c0:41");

The reason it doesn't happen automatically is probably because the known_hosts file isn't at $(user.home)/.ssh/known_hosts. You can also explicitly load known hosts from a specific location.

sshClient.loadKnownHosts(new File("path_to_known_hosts"));
0
Pranav On

You may set the SSH client to accept all keys without any verification (ignores host key verification)

SSHClient sshClient = new SSHClient();
sshClient.addHostKeyVerifier(new PromiscuousVerifier());
...
0
quantumferret On

If the server accepts keyboard-interactive verification, you can also do this, at least with recent versions of SSHJ:

client.addHostKeyVerifier(new ConsoleKnownHostsVerifier(new File(userKnownHostsFile), System.console()) {
    @Override
    protected boolean hostKeyUnverifiableAction(String hostname, PublicKey key) {
        try {
            entries().add(new HostEntry(null, hostname, KeyType.fromKey(key), key));
            write();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return true;
    }
});

This overrides the "Are you sure you want to continue connecting (yes/no)? " prompt that the user is supposed to reply to, so that you don't need to provide any input into a console to continue, while satisfying the keyboard-interactive authentication when a host is unknown and avoiding using a PromiscuousVerifier.

You can, of course, tweak the overriding method to your heart's content to add logging, and if you want to be prompted then just use a plain ConsoleKnownHostsVerifier.

If the server doesn't accept keyboard-interactive authentication and you still don't want to use the promiscuous verifier, then you could do something similar to the above for the OpenSSHKnownHosts class; e.g.:

HostKeyVerifier hkv = new OpenSSHKnownHosts(new File("~/.ssh/known_hosts") {
    @Override
    protected boolean hostKeyUnverifiableAction(String hostname, PublicKey key) {
        return true;
    }
};
client.addHostKeyVerifier(hkv);

Inside OpenSSHKnownHosts, all the hostKeyUnverifiableAction(...) method does is return false, so change that and you're good.

0
Ryaminal On

For an alternative answer ensure that the hostname you are trying to connect to is exactly a match in your known_hosts file. An example mistake that I was making was trying to connect to the full URL bob.insidenetwork.pvt but my known_hosts file had only bob as an entry because when I ssh manually I'm far too lazy to type the entire URL...

0
user6089682 On
try {
    ssh.connect(envConf.getIp(), port);
} catch (TransportException e) {
    if (e.getDisconnectReason() == DisconnectReason.HOST_KEY_NOT_VERIFIABLE) {
        String msg = e.getMessage();
        String[] split = msg.split("`");
        String vc = split[3];
        ssh = new SSHClient();
        ssh.addHostKeyVerifier(vc);
        ssh.connect(envConf.getIp(), port);
    } else {
        throw e;
    }
}
ssh.authPassword(envConf.getName(), envConf.getPw());
ssh.newSCPFileTransfer().download(envConf.getHomePath() + FilePath, toPath);