Public key authentication with Java over SSH

  1. Intro
  2. Generate Key Pair
  3. Copy public key to remote host
  4. Connect to remote host from java
  5. Source code

Intro

This article shows how to securely connect (i.e. establish ssh connection) to the remote host from java application. Also, configuration details for enabling public key authentication and protecting ssh keys will be provided.

Public key authentication enables users to establish an SSH connection without providing (i.e. typing in) explicit password. The immediate benefit is that the password is not transferred over the network, thus preventing the possibility of the password being compromised.

The private key should be stored in the ssh keychain and protected with the encryption passphrase.

Generate Key Pair

The first step is to generate a private/public key on the server where your java application will be running.

Private/public key pair can be generated by executing the following command:

ssh-keygen -t rsa

Here is the output from my local development box:

vladimir.stankovic@PCSVLADA ~
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/vladimir.stankovic/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/vladimir.stankovic/.ssh/id_rsa.
Your public key has been saved in /home/vladimir.stankovic/.ssh/id_rsa.pub.

Private key is identified as id_rsa and public key as a id_rsa.pub.

Copy public key to remote host

The ssh-copy-id copies the public key of your default identity (use -i identity_file for other identities) to the remote host.

vladimir.stankovic@PCSVLADA ~
$ ssh-copy-id -i /home/vladimir.stankovic/.ssh/id_rsa root@www.svlada.com
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@www.svlada.com's password:
Number of key(s) added: 1
Now try logging into the machine, with:   "ssh 'root@www.svlada.com'"
and check to make sure that only the key(s) you wanted were added.

Connect to remote host from java

I have used JSch library to establish SSH connection.

The most important part is configuration of com.jcraft.jsch.Session object and adding publickey to the list of PreferredAuthentication options.

Here is the sample code for configuring public key authentication:

    JSch jsch = new JSch();
    Session session = null;
    String privateKeyPath = "/home/vladimir.stankovic/.ssh/id_rsa";
    try {
        jsch.addIdentity(privateKeyPath);	    
        session = jsch.getSession(username, host, port);
        session.setConfig("PreferredAuthentications", "publickey,keyboard-interactive,password");
        java.util.Properties config = new java.util.Properties(); 
        config.put("StrictHostKeyChecking", "no");
        session.setConfig(config);
    } catch (JSchException e) {
        throw new RuntimeException("Failed to create Jsch Session object.", e);
    }

The next step is to connect to the remote host and execute an arbitrary command over SSH:

    String command = "echo \"Sit down, relax, mix yourself a drink and enjoy the show...\" >> /tmp/test.out";
    try {
        session.connect();
        Channel channel = session.openChannel("exec");
        ((ChannelExec) channel).setCommand(command);
        ((ChannelExec) channel).setPty(false);
        channel.connect();
        channel.disconnect();
        session.disconnect();
    } catch (JSchException e) {
        throw new RuntimeException("Error durring SSH command execution. Command: " + command);
    }

Source code

For a full example, you can check out code from the following git repository.