Package com.trilead.ssh2
Class KnownHosts
- java.lang.Object
-
- com.trilead.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 inknown_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:
- $Id: KnownHosts.java,v 1.2 2008/04/01 12:38:09 cplattne Exp $
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description private class
KnownHosts.KnownHostsEntry
-
Field Summary
Fields Modifier and Type Field Description static int
HOSTKEY_HAS_CHANGED
static int
HOSTKEY_IS_NEW
static int
HOSTKEY_IS_OK
private static Logger
LOGGER
private java.util.LinkedList<KnownHosts.KnownHostsEntry>
publicKeys
private static java.security.SecureRandom
SECURE_RANDOM
-
Constructor Summary
Constructors Constructor Description KnownHosts()
KnownHosts(char[] knownHostsData)
KnownHosts(java.io.File knownHosts)
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description 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.security.PublicKey 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.security.PublicKey
decodeHostKey(java.lang.String hostKeyAlgorithm, byte[] encodedHostKey)
private java.util.Vector<KnownHosts.KnownHostsEntry>
getAllKnownHostEntries(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.security.PublicKey key1, java.security.PublicKey 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.
-
-
-
Field Detail
-
LOGGER
private static final Logger LOGGER
-
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
-
SECURE_RANDOM
private static final java.security.SecureRandom SECURE_RANDOM
-
publicKeys
private final java.util.LinkedList<KnownHosts.KnownHostsEntry> publicKeys
-
-
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") - useaddHostkeyToFile()
for that purpose. This method is designed to be used in aServerHostKeyVerifier
.- 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 theServerHostKeyVerifier
.serverHostKey
- as passed to theServerHostKeyVerifier
.- Throws:
java.io.IOException
- on failure trying to convert the host key to a saveable format
-
addHostkeys
public void addHostkeys(char[] knownHostsData) throws java.io.IOException
Parses the given known_hosts data and adds entries to the database.- Parameters:
knownHostsData
- the known hosts data to parse- Throws:
java.io.IOException
- on failure reading the parsing the known hosts data
-
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
- the file to read the existing known hosts entries feom, add to add any new entries to- Throws:
java.io.IOException
- on failure reading the existing known hosts file
-
createHashedHostname
public static 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
- the hostname to hash- Returns:
- the hashed representation, e.g., "|1|cDhrv7zwEUV3k71CEPHnhHZezhA=|Xo+2y6rUXo2OIWRAYhBOIijbJMA="
-
hmacSha1Hash
private static byte[] hmacSha1Hash(byte[] salt, java.lang.String hostname)
-
checkHashed
private boolean checkHashed(java.lang.String entry, java.lang.String hostname)
-
checkKey
private int checkKey(java.lang.String remoteHostname, java.security.PublicKey remoteKey)
-
getAllKnownHostEntries
private java.util.Vector<KnownHosts.KnownHostsEntry> getAllKnownHostEntries(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. an ordered list of hostkey algorithms is returned which can be passed toConnection.setServerHostKeyAlgorithms
.- Parameters:
hostname
- the hostname (or hostname pattern) to search for- 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.
-
hostnameMatches
private 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 boolean matchKeys(java.security.PublicKey key1, java.security.PublicKey key2)
-
pseudoRegex
private 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 patternsserverHostKeyAlgorithm
- type of hostkey being verifiedserverHostKey
- the key blob- Returns:
HOSTKEY_IS_OK
: the given hostkey matches an entry for the given hostnameHOSTKEY_IS_NEW
: no entries found for this hostname and this type of hostkeyHOSTKEY_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.
-
decodeHostKey
private java.security.PublicKey decodeHostKey(java.lang.String hostKeyAlgorithm, byte[] encodedHostKey) throws java.io.IOException
- Throws:
java.io.IOException
-
addHostkeyToFile
public static 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 aServerHostKeyVerifier
.- 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 theServerHostKeyVerifier
.serverHostKey
- as passed to theServerHostKeyVerifier
.- Throws:
java.io.IOException
- on failure parsing the key or writing to file
-
rawFingerPrint
private static 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
- the type of key being fingerprintedhostkey
- the hostkey- Returns:
- the raw fingerprint
-
rawToHexFingerprint
private static 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 java.lang.String rawToBubblebabbleFingerprint(byte[] raw)
Convert a raw fingerprint to bubblebabble representation.- Parameters:
raw
- raw fingerprint- Returns:
- the bubblebabble representation
-
createHexFingerprint
public static 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
- the type of key being fingerprintedpublickey
- key blob- Returns:
- Hex fingerprint
-
createBubblebabbleFingerprint
public static 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
- the type of key being fingerprintedpublickey
- key data- Returns:
- Bubblebabble fingerprint
-
-