Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
* Please refer to the LICENSE.txt for licensing details.
*/
package ch.ethz.ssh2;
import java.io.BufferedReader;
import java.io.CharArrayReader;
import java.io.CharArrayWriter;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
import ch.ethz.ssh2.crypto.Base64;
import ch.ethz.ssh2.crypto.digest.Digest;
import ch.ethz.ssh2.crypto.digest.HMAC;
import ch.ethz.ssh2.crypto.digest.MD5;
import ch.ethz.ssh2.crypto.digest.SHA1;
import ch.ethz.ssh2.signature.DSAPublicKey;
import ch.ethz.ssh2.signature.DSASHA1Verify;
import ch.ethz.ssh2.signature.RSAPublicKey;
import ch.ethz.ssh2.signature.RSASHA1Verify;
import ch.ethz.ssh2.util.StringEncoder;
/**
* 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.
*
* @author Christian Plattner
* @version $Id: KnownHosts.java 86 2014-04-07 14:15:18Z [email protected] $
*/
public class KnownHosts
{
public static final int HOSTKEY_IS_OK = 0;
public static final int HOSTKEY_IS_NEW = 1;
public static final int HOSTKEY_HAS_CHANGED = 2;
private class KnownHostsEntry
{
String[] patterns;
Object key;
KnownHostsEntry(String[] patterns, Object key)
{
this.patterns = patterns;
this.key = key;
}
}
private final LinkedList publicKeys = new LinkedList();
public KnownHosts()
{
}
public KnownHosts(char[] knownHostsData) throws IOException
{
initialize(knownHostsData);
}
public KnownHosts(String knownHosts) throws IOException
{
initialize(new File(knownHosts));
}
public KnownHosts(File knownHosts) throws IOException
{
initialize(knownHosts);
}
/**
* 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 {@link ServerHostKeyVerifier}.
*
* @param 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.
* @param serverHostKeyAlgorithm as passed to the {@link ServerHostKeyVerifier}.
* @param serverHostKey as passed to the {@link ServerHostKeyVerifier}.
* @throws IOException
*/
public void addHostkey(String hostnames[], String serverHostKeyAlgorithm, byte[] serverHostKey) throws IOException
{
if (hostnames == null)
{
throw new IllegalArgumentException("hostnames may not be null");
}
if ("ssh-rsa".equals(serverHostKeyAlgorithm))
{
RSAPublicKey rpk = RSASHA1Verify.decodeSSHRSAPublicKey(serverHostKey);
synchronized (publicKeys)
{
publicKeys.add(new KnownHostsEntry(hostnames, rpk));
}
}
else if ("ssh-dss".equals(serverHostKeyAlgorithm))
{
DSAPublicKey dpk = DSASHA1Verify.decodeSSHDSAPublicKey(serverHostKey);
synchronized (publicKeys)
{
publicKeys.add(new KnownHostsEntry(hostnames, dpk));
}
}
else
{
throw new IOException("Unknwon host key type (" + serverHostKeyAlgorithm + ")");
}
}
/**
* Parses the given known_hosts data and adds entries to the database.
*
* @param knownHostsData
* @throws IOException
*/
public void addHostkeys(char[] knownHostsData) throws IOException
{
initialize(knownHostsData);
}
/**
* Parses the given known_hosts file and adds entries to the database.
*
* @param knownHosts
* @throws IOException
*/
public void addHostkeys(File knownHosts) throws IOException
{
initialize(knownHosts);
}
/**
* 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).
*
* @param hostname
* @return the hashed representation, e.g., "|1|cDhrv7zwEUV3k71CEPHnhHZezhA=|Xo+2y6rUXo2OIWRAYhBOIijbJMA="
*/
public static String createHashedHostname(String hostname)
{
SHA1 sha1 = new SHA1();
byte[] salt = new byte[sha1.getDigestLength()];
new SecureRandom().nextBytes(salt);
byte[] hash = hmacSha1Hash(salt, hostname);
String base64_salt = new String(Base64.encode(salt));
String base64_hash = new String(Base64.encode(hash));
return new String("|1|" + base64_salt + "|" + base64_hash);
}
private static byte[] hmacSha1Hash(byte[] salt, String hostname)
{
SHA1 sha1 = new SHA1();
if (salt.length != sha1.getDigestLength())
{
throw new IllegalArgumentException("Salt has wrong length (" + salt.length + ")");
}
HMAC hmac = new HMAC(sha1, salt, salt.length);
hmac.update(StringEncoder.GetBytes(hostname));
byte[] dig = new byte[hmac.getDigestLength()];
hmac.digest(dig);
return dig;
}
private boolean checkHashed(String entry, String hostname)
{
if (entry.startsWith("|1|") == false)
{
return false;
}
int delim_idx = entry.indexOf('|', 3);
if (delim_idx == -1)
{
return false;
}
String salt_base64 = entry.substring(3, delim_idx);
String hash_base64 = entry.substring(delim_idx + 1);
byte[] salt = null;
byte[] hash = null;
try
{
salt = Base64.decode(salt_base64.toCharArray());
hash = Base64.decode(hash_base64.toCharArray());
}
catch (IOException e)
{
return false;
}
SHA1 sha1 = new SHA1();
if (salt.length != sha1.getDigestLength())
{
return false;
}
byte[] dig = hmacSha1Hash(salt, hostname);
for (int i = 0; i < dig.length; i++)
{
if (dig[i] != hash[i])
{
return false;
}
}
return true;
}
private int checkKey(String remoteHostname, Object remoteKey)
{
int result = HOSTKEY_IS_NEW;
synchronized (publicKeys)
{
for (KnownHostsEntry ke : publicKeys)
{
if (hostnameMatches(ke.patterns, remoteHostname) == false)
{
continue;
}
boolean res = matchKeys(ke.key, remoteKey);
if (res == true)
{
return HOSTKEY_IS_OK;
}
result = HOSTKEY_HAS_CHANGED;
}
}
return result;
}
private List