package edu.washington.cs.publickey.ssl.server; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLSocket; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.jivesoftware.smack.util.Base64; public class SSLKeyManager { private static String KEY_ID = "PublicKey SSL Key"; public static String bytesToHex(byte[] data) { StringBuffer buf = new StringBuffer(); for (int i = 0; i < data.length; i++) { buf.append(byteToHex(data[i])); } return (buf.toString()); } public static String byteToHex(byte data) { StringBuffer buf = new StringBuffer(); buf.append(Integer.toHexString(0x0100 + (data & 0x00FF)).substring(1)); // buf.append(toHexChar((data >>> 4) & 0x0F)); // buf.append(toHexChar(data & 0x0F)); return buf.toString(); } private final KeyStore keyStore; private final File keyStoreFile; private final char[] password; private final SSLContext sslContext; public SSLKeyManager(File keyStore, char[] password) throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException, CertificateException, UnrecoverableKeyException, IOException, InterruptedException { this.keyStoreFile = keyStore; this.password = password; this.keyStore = createKeyStore(); this.sslContext = createSSLContext(); } private KeyStore createKeyStore() throws NoSuchAlgorithmException, IOException, InterruptedException, KeyStoreException, CertificateException, UnrecoverableKeyException, KeyManagementException { if (keyStoreFile == null) { throw new IOException("keystore file is null!"); } // Check if we need to create the file/dirs if (keyStoreFile.isDirectory()) { throw new IOException("keystore file is a directory, " + keyStoreFile.getAbsolutePath()); } else if (!keyStoreFile.exists()) { File parent = keyStoreFile.getParentFile(); if (!parent.exists()) { boolean success = keyStoreFile.mkdirs(); if (!success) { throw new IOException("unable to create directory: '" + parent.getAbsolutePath() + "'"); } } } // Create keystore. if (keyStoreFile.exists() == false) { System.out.println("Generating new keystore..."); byte[] randomStuff = new byte[16]; SecureRandom securerandom = SecureRandom.getInstance("SHA1PRNG"); securerandom.nextBytes(randomStuff); String stringName = bytesToHex(randomStuff); String stringPassword = new String(password); String[] cmd = new String[] { System.getProperty("java.home") + File.separator + "bin" + File.separator + "keytool", "-genkey", "-alias", KEY_ID, "-validity", "" + 100 * 365, "-keyalg", "RSA", "-keysize", "1024", "-dname", "CN=" + stringName, "-keystore", keyStoreFile.getPath(), "-keypass", stringPassword, "-storetype", "JKS", "-storepass", stringPassword }; Process process = Runtime.getRuntime().exec(cmd); process.waitFor(); BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; while ((line = in.readLine()) != null) { System.err.println(line); } BufferedReader err = new BufferedReader(new InputStreamReader(process.getErrorStream())); while ((line = err.readLine()) != null) { System.err.println(line); } if (process.exitValue() != 0) { throw new IOException("error creating ssl key"); } } // Open keystore. FileInputStream fileinputstream = new FileInputStream(keyStoreFile); KeyStore keystore = KeyStore.getInstance("JKS"); keystore.load(fileinputstream, password); String encodedPublicKey = Base64.encodeBytes(keystore.getCertificate(KEY_ID).getPublicKey().getEncoded(), Base64.DONT_BREAK_LINES); System.out.println("public key=" + encodedPublicKey); return keystore; } public SSLServerSocket createServerSocket(int serverPort) throws IOException { SSLServerSocket serverSocket = (SSLServerSocket) sslContext.getServerSocketFactory().createServerSocket(serverPort); return serverSocket; } public SSLSocket createClientSocket(String serverHost, int serverPort) throws IOException { SSLSocket socket = (SSLSocket) sslContext.getSocketFactory().createSocket(serverHost, serverPort); socket.setNeedClientAuth(true); return socket; } private SSLContext createSSLContext() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException, CertificateException, UnrecoverableKeyException, IOException, InterruptedException { // init SSL stuff KeyManagerFactory keymanagerfactory = KeyManagerFactory.getInstance("SunX509"); keymanagerfactory.init(keyStore, password); KeyManager[] arkeymanager = keymanagerfactory.getKeyManagers(); // Create trust manager, we accept any certificates (it will be // checked later) TrustManager[] osTrustManager = new TrustManager[] { new AllTrustingManager() }; SSLContext sslcontext = SSLContext.getInstance("SSL"); sslcontext.init(arkeymanager, osTrustManager, null); return sslcontext; } private static class AllTrustingManager implements X509TrustManager { public void checkClientTrusted(X509Certificate[] certs, String authType) { } public void checkServerTrusted(X509Certificate[] certs, String authType) { } public X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[0]; } } }