Class 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:
    $Id: KnownHosts.java,v 1.2 2008/04/01 12:38:09 cplattne Exp $
    • 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.
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • 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 - 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 to Connection.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 patterns
        serverHostKeyAlgorithm - type of hostkey being verified
        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.
      • 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 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 - 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 fingerprinted
        hostkey - 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 fingerprinted
        publickey - 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 fingerprinted
        publickey - key data
        Returns:
        Bubblebabble fingerprint