/** * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License version 2 only, as published by * the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU General Public License version 2 for more * details (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU General Public License version 2 * along with this work; if not, write to the Free Software Foundation, Inc., 51 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA or * visit www.oracle.com if you need additional information or have any * questions. */ import java.io.ByteArrayInputStream; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.security.KeyFactory; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.Principal; import java.security.PrivateKey; import java.security.SecureRandom; import java.security.UnrecoverableKeyException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; import java.util.List; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509ExtendedKeyManager; import javax.net.ssl.X509TrustManager; /** * Test that all ciphersuites work in all versions and all client authentication * types. The way this is setup the server is stateless and all checking is done * on the client side. */ public class CipherTestUtils { public static final int TIMEOUT = 20 * 1000; public static final SecureRandom secureRandom = new SecureRandom(); public static char[] PASSWORD = "passphrase".toCharArray(); private static final List TESTS = new ArrayList<>(3); private static final List EXCEPTIONS = new ArrayList<>(1); private static final String CLIENT_PUBLIC_KEY = "-----BEGIN CERTIFICATE-----\n" + "MIICtTCCAh4CCQDkYJ46DMcGRjANBgkqhkiG9w0BAQUFADCBnDELMAkGA1UEBhMC\n" + "VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MR8wHQYDVQQK\n" + "DBZTdW4gTWljcm9zeXN0ZW1zLCBJbmMuMSYwJAYDVQQLDB1TdW4gTWljcm9zeXN0\n" + "ZW1zIExhYm9yYXRvcmllczEfMB0GA1UEAwwWVGVzdCBDQSAoMTAyNCBiaXQgUlNB\n" + "KTAeFw0wOTA0MjcwNDA0MDhaFw0xMzA2MDUwNDA0MDhaMIGgMQswCQYDVQQGEwJV\n" + "UzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxHzAdBgNVBAoM\n" + "FlN1biBNaWNyb3N5c3RlbXMsIEluYy4xJjAkBgNVBAsMHVN1biBNaWNyb3N5c3Rl\n" + "bXMgTGFib3JhdG9yaWVzMSMwIQYDVQQDDBpUZXN0IENsaWVudCAoMTAyNCBiaXQg\n" + "UlNBKTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAm5rwjmhO7Nwd5GWs+KvQ\n" + "UnDiqpRDvRriOUFdF0rCI2Op24C+iwUMDGxPsgP7VkUpOdJhw3c72aP0CAWcZ5dN\n" + "UCW7WVDAxnogCahLCir1jjoGdEjiNGOy0L9sypsM9UvBzJN8uvXsxsTZX4Z88cKU\n" + "G7RUvN8LQ88zDljk5zr3c2MCAwEAATANBgkqhkiG9w0BAQUFAAOBgQA7LUDrzHln\n" + "EXuGmwZeeroACB6DVtkClMskF/Pj5GnTxoeNN9DggycX/eOeIDKRloHuMpBeZPJH\n" + "NUwFu4LB6HBDeldQD9iRp8zD/fPakOdN+1Gk5hciIZZJ5hQmeCl7Va2Gr64vUqZG\n" + "MkVU755t+7ByLgzWuhPhhsX9QCuPR5FjvQ==\n" + "-----END CERTIFICATE-----"; private static final String CLIENT_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n" + "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJua8I5oTuzcHeRl\n" + "rPir0FJw4qqUQ70a4jlBXRdKwiNjqduAvosFDAxsT7ID+1ZFKTnSYcN3O9mj9AgF\n" + "nGeXTVAlu1lQwMZ6IAmoSwoq9Y46BnRI4jRjstC/bMqbDPVLwcyTfLr17MbE2V+G\n" + "fPHClBu0VLzfC0PPMw5Y5Oc693NjAgMBAAECgYA5w73zj8Nk6J3sMNaShe3S/PcY\n" + "TewLopRCnwI46FbDnnbq9pNFtnzvi7HWKuY983THc1M5peTA+b1Y0QRr7F4Vg4x9\n" + "9UM0B/tZcIIcJJ3LS+9fXKCbYLQWq5F05JqeZu+i+QLmJFO5+2p7laeQ4oQfW7QE\n" + "YR4u2mSaLe0SsqHvOQJBAMhgcye9C6pJO0eo2/VtRxAXI7zxNAIjHwKo1cva7bhu\n" + "GdrMaEAJBAsMJ1GEk7/WDI+3KEbTjQdfIJuAvOR4FXUCQQDGzNn/tl2k93v/ugyM\n" + "/tBhCKDipYDIbyJMoG2AOtOGmCsiGo5L7idO4OAcm/QiHBQMXjFIVgTUcH8MhGj4\n" + "blJ3AkA5fUqsxRV6tuYWKkFpif/QgwMS65VDY7Y6+hvVECwSNSyf1PO4I54QWV1S\n" + "ixok+RHDjgY1Q+77hXSCiQ4o8rcdAkBHvjfR+5sx5IpgUGElJPRIgFenU3j1XH3x\n" + "T1gVFaWuhg3S4eiGaGzRH4BhcrqY8K8fg4Kfi0N08yA2gTZsqUujAkEAjuNPTuKx\n" + "ti0LXI09kbGUqOpRMm1zW5TD6LFeEaUN6oxrSZI2YUvu7VyotAqsxX5O0u0f3VQw\n" + "ySF0Q1oZ6qu7cg==\n" + "-----END PRIVATE KEY-----"; private static final String SERVER_PUBLIC_KEY = "-----BEGIN CERTIFICATE-----\n" + "MIICtTCCAh4CCQDkYJ46DMcGRTANBgkqhkiG9w0BAQUFADCBnDELMAkGA1UEBhMC\n" + "VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MR8wHQYDVQQK\n" + "DBZTdW4gTWljcm9zeXN0ZW1zLCBJbmMuMSYwJAYDVQQLDB1TdW4gTWljcm9zeXN0\n" + "ZW1zIExhYm9yYXRvcmllczEfMB0GA1UEAwwWVGVzdCBDQSAoMTAyNCBiaXQgUlNB\n" + "KTAeFw0wOTA0MjcwNDA0MDhaFw0xMzA2MDUwNDA0MDhaMIGgMQswCQYDVQQGEwJV\n" + "UzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxHzAdBgNVBAoM\n" + "FlN1biBNaWNyb3N5c3RlbXMsIEluYy4xJjAkBgNVBAsMHVN1biBNaWNyb3N5c3Rl\n" + "bXMgTGFib3JhdG9yaWVzMSMwIQYDVQQDDBpUZXN0IFNlcnZlciAoMTAyNCBiaXQg\n" + "UlNBKTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsHHeZ1O67yuxQKDSAOC\n" + "Xm271ViwBrXkxe5cvhG8MCCem6Z3XeZ/m6c2ucRwLaQxnmG1m0G6/OYaUXTivjcG\n" + "/K4bc1I+yjghAWQNLBtsOiP9w0LKibg3TSDehpeuuz/lmB5A4HMqQr8KkY4K7peD\n" + "1QkJ2Dn3zhbwQ/0d8f5CCbkCAwEAATANBgkqhkiG9w0BAQUFAAOBgQBOd8XojEnu\n" + "eTUHBwqfmnvRQvbICFDNbbL4KuX/JNPSy1WMGAEbNCTLZ+5yP69js8aUYqAk5vVf\n" + "dWRLU3MDiEzW7zxE1ubuKWjVuyGbG8Me0G01Hw+evBcZqB64Fz3OFISVfQh7MqE/\n" + "O0AeakRMH350FRLNl4o6KBSXmF/AADfqQQ==\n" + "-----END CERTIFICATE-----"; private static final String SERVER_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n" + "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAK7Bx3mdTuu8rsUC\n" + "g0gDgl5tu9VYsAa15MXuXL4RvDAgnpumd13mf5unNrnEcC2kMZ5htZtBuvzmGlF0\n" + "4r43BvyuG3NSPso4IQFkDSwbbDoj/cNCyom4N00g3oaXrrs/5ZgeQOBzKkK/CpGO\n" + "Cu6Xg9UJCdg5984W8EP9HfH+Qgm5AgMBAAECgYAXUv+3qJo+9mjxHHu/IdDFn6nB\n" + "ONwNmTtWe5DfQWi3l7LznU0zOC9x6+hu9NvwC4kf1XSyqxw04tVCZ/JXZurEmEBz\n" + "YtcQ5idRQDkKYXEDOeVUfvtHO6xilzrhPKxxd0GG/sei2pozikkqnYF3OcP0qL+a\n" + "3nWixZQBRoF2nIRLcQJBAN97TJBr0XTRmE7OCKLUy1+ws7vZB9uQ2efHMsgwOpsY\n" + "3cEW5qd95hrxLU72sBeu9loHQgBrT2Q3OAxnsPXmgO0CQQDIL3u9kS/O3Ukx+n1H\n" + "JdPFQCRxrDm/vtJpQEmq+mLqxxnxCFRIYQ2ieAPokBxWeMDtdWJGD3VxhahjPfZm\n" + "5K59AkEAuDVl0tVMfUIWjT5/F9jXGjUIsZofQ/iN5OLpFOHMLPO+Nd6umPjJpwON\n" + "GT11wM/S+DprSPUrJ6vsYy1FTCuHsQJBAMXtnO07xgdE6AAQaRmVnyMiXmY+IQMj\n" + "CyuhsrToyDDWFyIoWB0QSMjg3QxuoHYnAqpGK5qV4ksSGgG13BCz/okCQQCRHTgn\n" + "DuFG2f7GYLFjI4NaTEzHGp+J9LiNYY1kYYLonpwAC3Z5hzJVanYT3/g23AUZ/fdF\n" + "v5PDIViuPo5ZB1eD\n" + "-----END PRIVATE KEY-----"; private static final String CA_PUBLIC_KEY = "-----BEGIN CERTIFICATE-----\n" + "MIIDCDCCAnGgAwIBAgIJAIYlGfwNBY6NMA0GCSqGSIb3DQEBBQUAMIGcMQswCQYD\n" + "VQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxHzAd\n" + "BgNVBAoMFlN1biBNaWNyb3N5c3RlbXMsIEluYy4xJjAkBgNVBAsMHVN1biBNaWNy\n" + "b3N5c3RlbXMgTGFib3JhdG9yaWVzMR8wHQYDVQQDDBZUZXN0IENBICgxMDI0IGJp\n" + "dCBSU0EpMB4XDTA5MDQyNzA0MDQwOFoXDTEzMDYwNTA0MDQwOFowgZwxCzAJBgNV\n" + "BAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEfMB0G\n" + "A1UECgwWU3VuIE1pY3Jvc3lzdGVtcywgSW5jLjEmMCQGA1UECwwdU3VuIE1pY3Jv\n" + "c3lzdGVtcyBMYWJvcmF0b3JpZXMxHzAdBgNVBAMMFlRlc3QgQ0EgKDEwMjQgYml0\n" + "IFJTQSkwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOK4DJxxb0XX6MJ1CVjp\n" + "9Gmr/Ua8MS12R58F9lDpSKuq8cFexA4W7OdZ4jtbKv0tRHX5YxmbnXedwS+gdcOA\n" + "GRgXMoeXlgTFGpdL+TR8xKIlMGRSjnR7MpR2tRyIYI2p+UTEiD6LTlIm5Wh4z1q8\n" + "LYbxyMVD1XNNNymvPM44OjsBAgMBAAGjUDBOMB0GA1UdDgQWBBT27BLUflmfdtbi\n" + "WTgjwWnoxop2MTAfBgNVHSMEGDAWgBT27BLUflmfdtbiWTgjwWnoxop2MTAMBgNV\n" + "HRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAEQELNzhZpjnSgigd+QJ6I/3CPDo\n" + "SDkMLdP1BHlT/DkMIZvABm+M09ePNlWiLYCNCsL9nWmX0gw0rFDKsTklZyKTUzaM\n" + "oy/AZCrAaoIc6SO5m1xE1RMyVxd/Y/kg6cbfWxxCJFlMeU5rsSdC97HTE/lDyuoh\n" + "BmlOBB7SdR+1ScjA\n" + "-----END CERTIFICATE-----"; private static final String CA_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n" + "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOK4DJxxb0XX6MJ1\n" + "CVjp9Gmr/Ua8MS12R58F9lDpSKuq8cFexA4W7OdZ4jtbKv0tRHX5YxmbnXedwS+g\n" + "dcOAGRgXMoeXlgTFGpdL+TR8xKIlMGRSjnR7MpR2tRyIYI2p+UTEiD6LTlIm5Wh4\n" + "z1q8LYbxyMVD1XNNNymvPM44OjsBAgMBAAECgYEApmMOlk3FrQtsvjGof4GLp3Xa\n" + "tmvs54FzxKhagj0C4UHelNyYpAJ9MLjNiGQ7I31yTeaNrUCAi0XSfsKTSrwbLSnJ\n" + "qsUPKMBrnzcWrOyui2+cupHZXaTlNeYB97teLJYpa6Ql9CZLoTHoim1+//s7diBh\n" + "03Vls+M6Poi5PMvv59UCQQD+k/BiokmbBgWHfBY5cZSlx3Z4VTwSHJmHDTO3Tjso\n" + "EVErXUSVvqD/KHX6eM4VPM8lySV5djWV8lDsESCWMtiLAkEA4/xFNsiOLMQpxW/O\n" + "bt2tukxJkAxldD4lPoFZR+zbXtMtt8OjERtX2wD+nj6h7jfIeSyVuBEcBN8Uj8xe\n" + "kgfgIwJAPbKG4LCqHAsCjgpRrIxNVTwZByLJEy6hOqzFathn19cSj+rjs1Lm28/n\n" + "f9OFRnpdTbAJB/3REM0QNZYVCrG57wJBAN0KuTytZJNouaswhPCew5Kt5mDgc/kp\n" + "S8j3dk2zCto8W8Ygy1iJrzuqEjPxO+UQdrFtlde51vWuKGxnVIW3VwsCQEldqk7r\n" + "8y7PgquPP+k3L0OXno5wGBrPcW1+U0mhIZGnwSzE4SPX2ddqUSEUA/Av4RjAckL/\n" + "fpqmCkpTanyYW9U=\n" + "-----END PRIVATE KEY-----"; private final SSLSocketFactory factory; private final X509ExtendedKeyManager clientKeyManager; private final X509ExtendedKeyManager serverKeyManager; private final X509TrustManager clientTrustManager; private final X509TrustManager serverTrustManager; static abstract class Server implements Runnable { final CipherTestUtils cipherTest; Server(CipherTestUtils cipherTest) throws Exception { this.cipherTest = cipherTest; } @Override public abstract void run(); void handleRequest(InputStream in, OutputStream out) throws IOException { boolean newline = false; StringBuilder sb = new StringBuilder(); while (true) { int ch = in.read(); if (ch < 0) { throw new EOFException(); } sb.append((char) ch); if (ch == '\r') { // empty } else if (ch == '\n') { if (newline) { // 2nd newline in a row, end of request break; } newline = true; } else { newline = false; } } String request = sb.toString(); if (request.startsWith("GET / HTTP/1.") == false) { throw new IOException("Invalid request: " + request); } out.write("HTTP/1.0 200 OK\r\n\r\n".getBytes()); out.write("Tested Scenario: ".getBytes()); TestParameters tp = (TestParameters) CipherTestUtils.TESTS.get(0); out.write(tp.toString().getBytes()); out.write(" Test PASSED.".getBytes()); } } public static class TestParameters { String cipherSuite; String protocol; String clientAuth; TestParameters(String cipherSuite, String protocol, String clientAuth) { this.cipherSuite = cipherSuite; this.protocol = protocol; this.clientAuth = clientAuth; } boolean isEnabled() { return true; } @Override public String toString() { String s = cipherSuite + " in " + protocol + " mode"; if (clientAuth != null) { s += " with " + clientAuth + " client authentication"; } return s; } } private static volatile CipherTestUtils instance = null; public static CipherTestUtils getInstance() throws IOException, FileNotFoundException, KeyStoreException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, InvalidKeySpecException { if (instance == null) { synchronized (CipherTestUtils.class) { if (instance == null) { instance = new CipherTestUtils(); } } } return instance; } public static void setTestedArguments(String testedProtocol, String testedCipherSuite) { TestParameters testedParams; String cipherSuite = testedCipherSuite.trim(); if (cipherSuite.startsWith("SSL_")) { testedParams = new TestParameters(cipherSuite, testedProtocol, null); TESTS.add(testedParams); } else { System.out.println("Your input Cipher suites is not correct, " + "please try another one ."); } } public X509ExtendedKeyManager getClientKeyManager() { return clientKeyManager; } public X509TrustManager getClientTrustManager() { return clientTrustManager; } public X509ExtendedKeyManager getServerKeyManager() { return serverKeyManager; } public X509TrustManager getServerTrustManager() { return serverTrustManager; } public static void addFailure(Exception e) { EXCEPTIONS.add(e); } private CipherTestUtils() throws IOException, FileNotFoundException, KeyStoreException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, InvalidKeySpecException { factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); KeyStore serverKeyStore = createServerKeyStore(SERVER_PUBLIC_KEY, SERVER_PRIVATE_KEY); KeyStore serverTrustStore = createServerKeyStore(CA_PUBLIC_KEY, CA_PRIVATE_KEY); if (serverKeyStore != null) { KeyManagerFactory keyFactory1 = KeyManagerFactory.getInstance( KeyManagerFactory.getDefaultAlgorithm()); keyFactory1.init(serverKeyStore, PASSWORD); serverKeyManager = (X509ExtendedKeyManager) keyFactory1. getKeyManagers()[0]; } else { serverKeyManager = null; } serverTrustManager = serverTrustStore != null ? new AlwaysTrustManager(serverTrustStore) : null; KeyStore clientKeyStore, clientTrustStore; clientTrustStore = serverTrustStore; clientKeyStore = createServerKeyStore(CLIENT_PUBLIC_KEY,CLIENT_PRIVATE_KEY); if (clientKeyStore != null) { KeyManagerFactory keyFactory = KeyManagerFactory.getInstance( KeyManagerFactory.getDefaultAlgorithm()); keyFactory.init(clientKeyStore, PASSWORD); clientKeyManager = (X509ExtendedKeyManager) keyFactory. getKeyManagers()[0]; } else { clientKeyManager = null; } clientTrustManager = (clientTrustStore != null) ? new AlwaysTrustManager(clientTrustStore) : null; } void checkResult(String exception) throws Exception { if (EXCEPTIONS.size() >= 1) { Exception actualException = EXCEPTIONS.get(0); if (exception == null) { throw new RuntimeException("FAILED: got unexpected exception: " + actualException); } if (!exception.equals(actualException.getClass().getName())) { throw new RuntimeException("FAILED: got unexpected exception: " + actualException); } System.out.println("PASSED: got expected exception: " + actualException); } else { if (exception != null) { throw new RuntimeException("FAILED: " + exception + " was expected"); } System.out.println("PASSED"); } } SSLSocketFactory getFactory() { return factory; } static abstract class Client implements Runnable { final CipherTestUtils cipherTest; TestParameters testedParams; Client(CipherTestUtils cipherTest) throws Exception { this.cipherTest = cipherTest; } Client(CipherTestUtils cipherTest, String testedCipherSuite) throws Exception { this.cipherTest = cipherTest; } @Override public final void run() { TESTS.stream().map((params) -> { if (!params.isEnabled()) { System.out.println("Skipping disabled test " + params); } return params; }).forEach((params) -> { try { System.out.println("Testing " + params); runTest(params); System.out.println("Passed " + params); } catch (Exception e) { CipherTestUtils.addFailure(e); System.out.println("** Failed " + params + "**, got exception:"); e.printStackTrace(System.err); } }); } abstract void runTest(TestParameters params) throws Exception; void sendRequest(InputStream in, OutputStream out) throws IOException { out.write("GET / HTTP/1.0\r\n\r\n".getBytes()); out.flush(); StringBuilder sb = new StringBuilder(); while (true) { int ch = in.read(); if (ch < 0) { break; } sb.append((char) ch); } String response = sb.toString(); if (response.startsWith("HTTP/1.0 200 ") == false) { throw new IOException("Invalid response: " + response); } else { System.out.println(); System.out.println("--- Response --- "); System.out.println(response); System.out.println("---------------- "); } } } public static void printStringArray(String[] stringArray) { System.out.print(stringArray.length + " : "); for (String stringArray1 : stringArray) { System.out.print(stringArray1); System.out.print(","); } System.out.println(); } public static void printInfo(SSLServerSocket socket) { System.out.println(); System.out.println("--- SSL ServerSocket Info ---"); System.out.print("SupportedProtocols : "); printStringArray(socket.getSupportedProtocols()); System.out.print("SupportedCipherSuites : "); printStringArray(socket.getSupportedCipherSuites()); System.out.print("EnabledProtocols : "); printStringArray(socket.getEnabledProtocols()); System.out.print("EnabledCipherSuites : "); String[] supportedCipherSuites = socket.getEnabledCipherSuites(); Arrays.sort(supportedCipherSuites); printStringArray(supportedCipherSuites); System.out.println("NeedClientAuth : " + socket.getNeedClientAuth()); System.out.println("WantClientAuth : " + socket.getWantClientAuth()); System.out.println("-----------------------"); } public static void printInfo(SSLSocket socket) { System.out.println(); System.out.println("--- SSL Socket Info ---"); System.out.print(" SupportedProtocols : "); printStringArray(socket.getSupportedProtocols()); System.out.println(" EnabledProtocols : " + socket.getEnabledProtocols()[0]); System.out.print(" SupportedCipherSuites : "); String[] supportedCipherSuites = socket.getEnabledCipherSuites(); Arrays.sort(supportedCipherSuites); printStringArray(supportedCipherSuites); System.out.println(" EnabledCipherSuites : " + socket.getEnabledCipherSuites()[0]); System.out.println(" NeedClientAuth : " + socket.getNeedClientAuth()); System.out.println(" WantClientAuth : " + socket.getWantClientAuth()); System.out.println("-----------------------"); } private static KeyStore createServerKeyStore(String publicKeyStr, String keySpecStr) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, InvalidKeySpecException { KeyStore ks = KeyStore.getInstance("JKS"); ks.load(null, null); if (publicKeyStr == null || keySpecStr == null) { throw new IllegalArgumentException("publicKeyStr or " + "keySpecStr cannot be null"); } String strippedPrivateKey = keySpecStr.substring( keySpecStr.indexOf("\n"), keySpecStr.lastIndexOf("\n")); // generate the private key. PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( Base64.getMimeDecoder().decode(strippedPrivateKey)); KeyFactory kf = KeyFactory.getInstance("RSA"); RSAPrivateKey priKey = (RSAPrivateKey) kf.generatePrivate(priKeySpec); // generate certificate chain try (InputStream is = new ByteArrayInputStream(publicKeyStr.getBytes())) { // generate certificate from cert string CertificateFactory cf = CertificateFactory.getInstance("X.509"); Certificate keyCert = cf.generateCertificate(is); Certificate[] chain = {keyCert}; ks.setKeyEntry("TestEntry", priKey, PASSWORD, chain); } return ks; } public static void main(PeerFactory peerFactory, String mode, String expectedException) throws Exception { long time = System.currentTimeMillis(); setTestedArguments(peerFactory.getTestedProtocol(), peerFactory.getTestedCipher()); System.out.print( " Initializing test '" + peerFactory.getName() + "'..."); secureRandom.nextInt(); CipherTestUtils cipherTest = CipherTestUtils.getInstance(); if (mode.equalsIgnoreCase("Server")) { // server mode Thread serverThread = new Thread(peerFactory.newServer(cipherTest), "Server"); serverThread.start(); } else if (mode.equalsIgnoreCase("Client")) { peerFactory.newClient(cipherTest).run(); cipherTest.checkResult(expectedException); JSSEServer.closeServer = true; } else { throw new RuntimeException("unsupported mode"); } time = System.currentTimeMillis() - time; System.out.println("Elapsed time " + time); } public static abstract class PeerFactory { abstract String getName(); abstract String getTestedProtocol(); abstract String getTestedCipher(); abstract Client newClient(CipherTestUtils cipherTest) throws Exception; abstract Server newServer(CipherTestUtils cipherTest) throws Exception; boolean isSupported(String cipherSuite) { return true; } } } class AlwaysTrustManager implements X509TrustManager { X509TrustManager trustManager; public AlwaysTrustManager(KeyStore keyStore) throws NoSuchAlgorithmException, KeyStoreException { TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory. getDefaultAlgorithm()); tmf.init(keyStore); TrustManager tms[] = tmf.getTrustManagers(); for (TrustManager tm : tms) { trustManager = (X509TrustManager) tm; return; } } @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { try { trustManager.checkClientTrusted(chain, authType); } catch (CertificateException excep) { System.out.println("ERROR in client trust manager"); } } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { try { trustManager.checkServerTrusted(chain, authType); } catch (CertificateException excep) { System.out.println("ERROR in server Trust manger"); } } @Override public X509Certificate[] getAcceptedIssuers() { return trustManager.getAcceptedIssuers(); } } class MyX509KeyManager extends X509ExtendedKeyManager { private final X509ExtendedKeyManager keyManager; private String authType; MyX509KeyManager(X509ExtendedKeyManager keyManager) { this.keyManager = keyManager; } void setAuthType(String authType) { this.authType = "ECDSA".equals(authType) ? "EC" : authType; } @Override public String[] getClientAliases(String keyType, Principal[] issuers) { if (authType == null) { return null; } return keyManager.getClientAliases(authType, issuers); } @Override public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) { if (authType == null) { return null; } return keyManager.chooseClientAlias(new String[]{authType}, issuers, socket); } @Override public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, SSLEngine engine) { if (authType == null) { return null; } return keyManager.chooseEngineClientAlias(new String[]{authType}, issuers, engine); } @Override public String[] getServerAliases(String keyType, Principal[] issuers) { throw new UnsupportedOperationException("Servers not supported"); } @Override public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) { throw new UnsupportedOperationException("Servers not supported"); } @Override public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine) { throw new UnsupportedOperationException("Servers not supported"); } @Override public X509Certificate[] getCertificateChain(String alias) { return keyManager.getCertificateChain(alias); } @Override public PrivateKey getPrivateKey(String alias) { return keyManager.getPrivateKey(alias); } }