ch.ethz.ssh2
Class KnownHosts

java.lang.Object
  extended by ch.ethz.ssh2.KnownHosts

public class KnownHosts
extends java.lang.Object

The KnownHosts class is a handy tool to verify received server hostkeys based on the information in known_hosts files (the ones used by OpenSSH).

It offers basically an in-memory database for known_hosts entries, as well as some helper functions. Entries from a known_hosts file can be loaded at construction time. It is also possible to add more keys later (e.g., one can parse different known_hosts files).

It is a thread safe implementation, therefore, you need only to instantiate one KnownHosts for your whole application.

Version:
2.50, 03/15/10
Author:
Christian Plattner

Nested Class Summary
private  class KnownHosts.KnownHostsEntry
           
 
Field Summary
static int HOSTKEY_HAS_CHANGED
           
static int HOSTKEY_IS_NEW
           
static int HOSTKEY_IS_OK
           
private  java.util.LinkedList publicKeys
           
 
Constructor Summary
KnownHosts()
           
KnownHosts(char[] knownHostsData)
           
KnownHosts(java.io.File knownHosts)
           
 
Method Summary
 void addHostkey(java.lang.String[] hostnames, java.lang.String serverHostKeyAlgorithm, byte[] serverHostKey)
          Adds a single public key entry to the database.
 void addHostkeys(char[] knownHostsData)
          Parses the given known_hosts data and adds entries to the database.
 void addHostkeys(java.io.File knownHosts)
          Parses the given known_hosts file and adds entries to the database.
static void addHostkeyToFile(java.io.File knownHosts, java.lang.String[] hostnames, java.lang.String serverHostKeyAlgorithm, byte[] serverHostKey)
          Adds a single public key entry to the a known_hosts file.
private  boolean checkHashed(java.lang.String entry, java.lang.String hostname)
           
private  int checkKey(java.lang.String remoteHostname, java.lang.Object remoteKey)
           
static java.lang.String createBubblebabbleFingerprint(java.lang.String keytype, byte[] publickey)
          Convert a ssh2 key-blob into a human readable bubblebabble fingerprint.
static java.lang.String createHashedHostname(java.lang.String hostname)
          Generate the hashed representation of the given hostname.
static java.lang.String createHexFingerprint(java.lang.String keytype, byte[] publickey)
          Convert a ssh2 key-blob into a human readable hex fingerprint.
private  java.util.Vector getAllKeys(java.lang.String hostname)
           
 java.lang.String[] getPreferredServerHostkeyAlgorithmOrder(java.lang.String hostname)
          Try to find the preferred order of hostkey algorithms for the given hostname.
private static byte[] hmacSha1Hash(byte[] salt, java.lang.String hostname)
           
private  boolean hostnameMatches(java.lang.String[] hostpatterns, java.lang.String hostname)
           
private  void initialize(char[] knownHostsData)
           
private  void initialize(java.io.File knownHosts)
           
private  boolean matchKeys(java.lang.Object key1, java.lang.Object key2)
           
private  boolean pseudoRegex(char[] pattern, int i, char[] match, int j)
           
private static byte[] rawFingerPrint(java.lang.String type, java.lang.String keyType, byte[] hostkey)
          Generates a "raw" fingerprint of a hostkey.
private static java.lang.String rawToBubblebabbleFingerprint(byte[] raw)
          Convert a raw fingerprint to bubblebabble representation.
private static java.lang.String rawToHexFingerprint(byte[] fingerprint)
          Convert a raw fingerprint to hex representation (XX:YY:ZZ...).
private  java.lang.String[] recommendHostkeyAlgorithms(java.lang.String hostname)
           
 int verifyHostkey(java.lang.String hostname, java.lang.String serverHostKeyAlgorithm, byte[] serverHostKey)
          Checks the internal hostkey database for the given hostkey.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

HOSTKEY_IS_OK

public static final int HOSTKEY_IS_OK
See Also:
Constant Field Values

HOSTKEY_IS_NEW

public static final int HOSTKEY_IS_NEW
See Also:
Constant Field Values

HOSTKEY_HAS_CHANGED

public static final int HOSTKEY_HAS_CHANGED
See Also:
Constant Field Values

publicKeys

private java.util.LinkedList publicKeys
Constructor Detail

KnownHosts

public KnownHosts()

KnownHosts

public KnownHosts(char[] knownHostsData)
           throws java.io.IOException
Throws:
java.io.IOException

KnownHosts

public KnownHosts(java.io.File knownHosts)
           throws java.io.IOException
Throws:
java.io.IOException
Method Detail

addHostkey

public void addHostkey(java.lang.String[] hostnames,
                       java.lang.String serverHostKeyAlgorithm,
                       byte[] serverHostKey)
                throws java.io.IOException
Adds a single public key entry to the database. Note: this will NOT add the public key to any physical file (e.g., "~/.ssh/known_hosts") - use addHostkeyToFile() for that purpose. This method is designed to be used in a ServerHostKeyVerifier.

Parameters:
hostnames - a list of hostname patterns - at least one most be specified. Check out the OpenSSH sshd man page for a description of the pattern matching algorithm.
serverHostKeyAlgorithm - as passed to the ServerHostKeyVerifier.
serverHostKey - as passed to the ServerHostKeyVerifier.
Throws:
java.io.IOException

addHostkeys

public void addHostkeys(char[] knownHostsData)
                 throws java.io.IOException
Parses the given known_hosts data and adds entries to the database.

Parameters:
knownHostsData -
Throws:
java.io.IOException

addHostkeys

public void addHostkeys(java.io.File knownHosts)
                 throws java.io.IOException
Parses the given known_hosts file and adds entries to the database.

Parameters:
knownHosts -
Throws:
java.io.IOException

createHashedHostname

public static final java.lang.String createHashedHostname(java.lang.String hostname)
Generate the hashed representation of the given hostname. Useful for adding entries with hashed hostnames to a known_hosts file. (see -H option of OpenSSH key-gen).

Parameters:
hostname -
Returns:
the hashed representation, e.g., "|1|cDhrv7zwEUV3k71CEPHnhHZezhA=|Xo+2y6rUXo2OIWRAYhBOIijbJMA="

hmacSha1Hash

private static final byte[] hmacSha1Hash(byte[] salt,
                                         java.lang.String hostname)

checkHashed

private final boolean checkHashed(java.lang.String entry,
                                  java.lang.String hostname)

checkKey

private int checkKey(java.lang.String remoteHostname,
                     java.lang.Object remoteKey)

getAllKeys

private java.util.Vector getAllKeys(java.lang.String hostname)

getPreferredServerHostkeyAlgorithmOrder

public java.lang.String[] getPreferredServerHostkeyAlgorithmOrder(java.lang.String hostname)
Try to find the preferred order of hostkey algorithms for the given hostname. Based on the type of hostkey that is present in the internal database (i.e., either ssh-rsa or ssh-dss) an ordered list of hostkey algorithms is returned which can be passed to Connection.setServerHostKeyAlgorithms.

Parameters:
hostname -
Returns:
null if no key for the given hostname is present or there are keys of multiple types present for the given hostname. Otherwise, an array with hostkey algorithms is returned (i.e., an array of length 2).

hostnameMatches

private final boolean hostnameMatches(java.lang.String[] hostpatterns,
                                      java.lang.String hostname)

initialize

private void initialize(char[] knownHostsData)
                 throws java.io.IOException
Throws:
java.io.IOException

initialize

private void initialize(java.io.File knownHosts)
                 throws java.io.IOException
Throws:
java.io.IOException

matchKeys

private final boolean matchKeys(java.lang.Object key1,
                                java.lang.Object key2)

pseudoRegex

private final boolean pseudoRegex(char[] pattern,
                                  int i,
                                  char[] match,
                                  int j)

recommendHostkeyAlgorithms

private java.lang.String[] recommendHostkeyAlgorithms(java.lang.String hostname)

verifyHostkey

public int verifyHostkey(java.lang.String hostname,
                         java.lang.String serverHostKeyAlgorithm,
                         byte[] serverHostKey)
                  throws java.io.IOException
Checks the internal hostkey database for the given hostkey. If no matching key can be found, then the hostname is resolved to an IP address and the search is repeated using that IP address.

Parameters:
hostname - the server's hostname, will be matched with all hostname patterns
serverHostKeyAlgorithm - type of hostkey, either ssh-rsa or ssh-dss
serverHostKey - the key blob
Returns:
  • HOSTKEY_IS_OK: the given hostkey matches an entry for the given hostname
  • HOSTKEY_IS_NEW: no entries found for this hostname and this type of hostkey
  • HOSTKEY_HAS_CHANGED: hostname is known, but with another key of the same type (man-in-the-middle attack?)
Throws:
java.io.IOException - if the supplied key blob cannot be parsed or does not match the given hostkey type.

addHostkeyToFile

public static final void addHostkeyToFile(java.io.File knownHosts,
                                          java.lang.String[] hostnames,
                                          java.lang.String serverHostKeyAlgorithm,
                                          byte[] serverHostKey)
                                   throws java.io.IOException
Adds a single public key entry to the a known_hosts file. This method is designed to be used in a ServerHostKeyVerifier.

Parameters:
knownHosts - the file where the publickey entry will be appended.
hostnames - a list of hostname patterns - at least one most be specified. Check out the OpenSSH sshd man page for a description of the pattern matching algorithm.
serverHostKeyAlgorithm - as passed to the ServerHostKeyVerifier.
serverHostKey - as passed to the ServerHostKeyVerifier.
Throws:
java.io.IOException

rawFingerPrint

private static final byte[] rawFingerPrint(java.lang.String type,
                                           java.lang.String keyType,
                                           byte[] hostkey)
Generates a "raw" fingerprint of a hostkey.

Parameters:
type - either "md5" or "sha1"
keyType - either "ssh-rsa" or "ssh-dss"
hostkey - the hostkey
Returns:
the raw fingerprint

rawToHexFingerprint

private static final java.lang.String rawToHexFingerprint(byte[] fingerprint)
Convert a raw fingerprint to hex representation (XX:YY:ZZ...).

Parameters:
fingerprint - raw fingerprint
Returns:
the hex representation

rawToBubblebabbleFingerprint

private static final java.lang.String rawToBubblebabbleFingerprint(byte[] raw)
Convert a raw fingerprint to bubblebabble representation.

Parameters:
raw - raw fingerprint
Returns:
the bubblebabble representation

createHexFingerprint

public static final java.lang.String createHexFingerprint(java.lang.String keytype,
                                                          byte[] publickey)
Convert a ssh2 key-blob into a human readable hex fingerprint. Generated fingerprints are identical to those generated by OpenSSH.

Example fingerprint: d0:cb:76:19:99:5a:03:fc:73:10:70:93:f2:44:63:47.

Parameters:
keytype - either "ssh-rsa" or "ssh-dss"
publickey - key blob
Returns:
Hex fingerprint

createBubblebabbleFingerprint

public static final java.lang.String createBubblebabbleFingerprint(java.lang.String keytype,
                                                                   byte[] publickey)
Convert a ssh2 key-blob into a human readable bubblebabble fingerprint. The used bubblebabble algorithm (taken from OpenSSH) generates fingerprints that are easier to remember for humans.

Example fingerprint: xofoc-bubuz-cazin-zufyl-pivuk-biduk-tacib-pybur-gonar-hotat-lyxux.

Parameters:
keytype - either "ssh-rsa" or "ssh-dss"
publickey - key data
Returns:
Bubblebabble fingerprint