1 /*
   2  * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 //
  25 // Please run in othervm mode.  SunJSSE does not support dynamic system
  26 // properties, no way to re-use system properties in samevm/agentvm mode.
  27 //
  28 
  29 /*
  30  * @test
  31  * @bug 8161106 8170329
  32  * @summary Improve SSLSocket test template
  33  * @run main/othervm SSLSocketTemplate
  34  */
  35 
  36 import java.io.ByteArrayInputStream;
  37 import java.io.InputStream;
  38 import java.io.IOException;
  39 import java.io.OutputStream;
  40 import javax.net.ssl.KeyManagerFactory;
  41 import javax.net.ssl.SSLContext;
  42 import javax.net.ssl.SSLServerSocket;
  43 import javax.net.ssl.SSLServerSocketFactory;
  44 import javax.net.ssl.SSLSocket;
  45 import javax.net.ssl.SSLSocketFactory;
  46 import javax.net.ssl.TrustManagerFactory;
  47 import java.net.InetSocketAddress;
  48 import java.net.SocketTimeoutException;
  49 import java.security.KeyStore;
  50 import java.security.PrivateKey;
  51 import java.security.KeyFactory;
  52 import java.security.cert.Certificate;
  53 import java.security.cert.CertificateFactory;
  54 import java.security.spec.PKCS8EncodedKeySpec;
  55 import java.util.Base64;
  56 
  57 import java.util.concurrent.CountDownLatch;
  58 import java.util.concurrent.TimeUnit;
  59 
  60 /**
  61  * Template to help speed your client/server tests.
  62  *
  63  * Two examples that use this template:
  64  *    test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java
  65  *    test/sun/net/www/protocol/https/HttpsClient/ServerIdentityTest.java
  66  */
  67 public class SSLSocketTemplate {
  68 
  69     /*
  70      * ==================
  71      * Run the test case.
  72      */
  73     public static void main(String[] args) throws Exception {
  74         (new SSLSocketTemplate()).run();
  75     }
  76 
  77     /*
  78      * Run the test case.
  79      */
  80     public void run() throws Exception {
  81         bootup();
  82     }
  83 
  84     /*
  85      * Define the server side application of the test for the specified socket.
  86      */
  87     protected void runServerApplication(SSLSocket socket) throws Exception {
  88         // here comes the test logic
  89         InputStream sslIS = socket.getInputStream();
  90         OutputStream sslOS = socket.getOutputStream();
  91 
  92         sslIS.read();
  93         sslOS.write(85);
  94         sslOS.flush();
  95     }
  96 
  97     /*
  98      * Define the client side application of the test for the specified socket.
  99      * This method is used if the returned value of
 100      * isCustomizedClientConnection() is false.
 101      *
 102      * @param socket may be null is no client socket is generated.
 103      *
 104      * @see #isCustomizedClientConnection()
 105      */
 106     protected void runClientApplication(SSLSocket socket) throws Exception {
 107         InputStream sslIS = socket.getInputStream();
 108         OutputStream sslOS = socket.getOutputStream();
 109 
 110         sslOS.write(280);
 111         sslOS.flush();
 112         sslIS.read();
 113     }
 114 
 115     /*
 116      * Define the client side application of the test for the specified
 117      * server port.  This method is used if the returned value of
 118      * isCustomizedClientConnection() is true.
 119      *
 120      * Note that the client need to connect to the server port by itself
 121      * for the actual message exchange.
 122      *
 123      * @see #isCustomizedClientConnection()
 124      */
 125     protected void runClientApplication(int serverPort) throws Exception {
 126         // blank
 127     }
 128 
 129     /*
 130      * Create an instance of SSLContext for client use.
 131      */
 132     protected SSLContext createClientSSLContext() throws Exception {
 133         return createSSLContext(trustedCertStrs,
 134                 endEntityCertStrs, endEntityPrivateKeys,
 135                 endEntityPrivateKeyAlgs,
 136                 endEntityPrivateKeyNames,
 137                 getClientContextParameters());
 138     }
 139 
 140     /*
 141      * Create an instance of SSLContext for server use.
 142      */
 143     protected SSLContext createServerSSLContext() throws Exception {
 144         return createSSLContext(trustedCertStrs,
 145                 endEntityCertStrs, endEntityPrivateKeys,
 146                 endEntityPrivateKeyAlgs,
 147                 endEntityPrivateKeyNames,
 148                 getServerContextParameters());
 149     }
 150 
 151     /*
 152      * The parameters used to configure SSLContext.
 153      */
 154     protected static final class ContextParameters {
 155         final String contextProtocol;
 156         final String tmAlgorithm;
 157         final String kmAlgorithm;
 158 
 159         ContextParameters(String contextProtocol,
 160                 String tmAlgorithm, String kmAlgorithm) {
 161 
 162             this.contextProtocol = contextProtocol;
 163             this.tmAlgorithm = tmAlgorithm;
 164             this.kmAlgorithm = kmAlgorithm;
 165         }
 166     }
 167 
 168     /*
 169      * Get the client side parameters of SSLContext.
 170      */
 171     protected ContextParameters getClientContextParameters() {
 172         return new ContextParameters("TLS", "PKIX", "NewSunX509");
 173     }
 174 
 175     /*
 176      * Get the server side parameters of SSLContext.
 177      */
 178     protected ContextParameters getServerContextParameters() {
 179         return new ContextParameters("TLS", "PKIX", "NewSunX509");
 180     }
 181 
 182     /*
 183      * Does the client side use customized connection other than
 184      * explicit Socket.connect(), for example, URL.openConnection()?
 185      */
 186     protected boolean isCustomizedClientConnection() {
 187         return false;
 188     }
 189 
 190     /*
 191      * Configure the client side socket.
 192      */
 193     protected void configureClientSocket(SSLSocket socket) {
 194     }
 195 
 196     /*
 197      * Configure the server side socket.
 198      */
 199     protected void configureServerSocket(SSLServerSocket socket) {
 200     }
 201 
 202     /*
 203      * =============================================
 204      * Define the client and server side operations.
 205      *
 206      * If the client or server is doing some kind of object creation
 207      * that the other side depends on, and that thread prematurely
 208      * exits, you may experience a hang.  The test harness will
 209      * terminate all hung threads after its timeout has expired,
 210      * currently 3 minutes by default, but you might try to be
 211      * smart about it....
 212      */
 213 
 214     /*
 215      * Is the server ready to serve?
 216      */
 217     private final CountDownLatch serverCondition = new CountDownLatch(1);
 218 
 219     /*
 220      * Is the client ready to handshake?
 221      */
 222     private final CountDownLatch clientCondition = new CountDownLatch(1);
 223 
 224     /*
 225      * What's the server port?  Use any free port by default
 226      */
 227     private volatile int serverPort = 0;
 228 
 229     /*
 230      * Define the server side of the test.
 231      */
 232     private void doServerSide() throws Exception {
 233         // kick start the server side service
 234         SSLContext context = createServerSSLContext();
 235         SSLServerSocketFactory sslssf = context.getServerSocketFactory();
 236         SSLServerSocket sslServerSocket =
 237                 (SSLServerSocket)sslssf.createServerSocket(serverPort);
 238         configureServerSocket(sslServerSocket);
 239         serverPort = sslServerSocket.getLocalPort();
 240 
 241         // Signal the client, the server is ready to accept connection.
 242         serverCondition.countDown();
 243 
 244         // Try to accept a connection in 30 seconds.
 245         SSLSocket sslSocket;
 246         try {
 247             sslServerSocket.setSoTimeout(30000);
 248             sslSocket = (SSLSocket)sslServerSocket.accept();
 249         } catch (SocketTimeoutException ste) {
 250             // Ignore the test case if no connection within 30 seconds.
 251             System.out.println(
 252                 "No incoming client connection in 30 seconds. " +
 253                 "Ignore in server side.");
 254             return;
 255         } finally {
 256             sslServerSocket.close();
 257         }
 258 
 259         // handle the connection
 260         try {
 261             // Is it the expected client connection?
 262             //
 263             // Naughty test cases or third party routines may try to
 264             // connection to this server port unintentionally.  In
 265             // order to mitigate the impact of unexpected client
 266             // connections and avoid intermittent failure, it should
 267             // be checked that the accepted connection is really linked
 268             // to the expected client.
 269             boolean clientIsReady =
 270                     clientCondition.await(30L, TimeUnit.SECONDS);
 271 
 272             if (clientIsReady) {
 273                 // Run the application in server side.
 274                 runServerApplication(sslSocket);
 275             } else {    // Otherwise, ignore
 276                 // We don't actually care about plain socket connections
 277                 // for TLS communication testing generally.  Just ignore
 278                 // the test if the accepted connection is not linked to
 279                 // the expected client or the client connection timeout
 280                 // in 30 seconds.
 281                 System.out.println(
 282                         "The client is not the expected one or timeout. " +
 283                         "Ignore in server side.");
 284             }
 285         } finally {
 286             sslSocket.close();
 287         }
 288     }
 289 
 290     /*
 291      * Define the client side of the test.
 292      */
 293     private void doClientSide() throws Exception {
 294 
 295         // Wait for server to get started.
 296         //
 297         // The server side takes care of the issue if the server cannot
 298         // get started in 90 seconds.  The client side would just ignore
 299         // the test case if the serer is not ready.
 300         boolean serverIsReady =
 301                 serverCondition.await(90L, TimeUnit.SECONDS);
 302         if (!serverIsReady) {
 303             System.out.println(
 304                     "The server is not ready yet in 90 seconds. " +
 305                     "Ignore in client side.");
 306             return;
 307         }
 308 
 309         if (isCustomizedClientConnection()) {
 310             // Signal the server, the client is ready to communicate.
 311             clientCondition.countDown();
 312 
 313             // Run the application in client side.
 314             runClientApplication(serverPort);
 315 
 316             return;
 317         }
 318 
 319         SSLContext context = createClientSSLContext();
 320         SSLSocketFactory sslsf = context.getSocketFactory();
 321 
 322         try (SSLSocket sslSocket = (SSLSocket)sslsf.createSocket()) {
 323             try {
 324                 configureClientSocket(sslSocket);
 325                 sslSocket.connect(
 326                         new InetSocketAddress("localhost", serverPort), 15000);
 327             } catch (IOException ioe) {
 328                 // The server side may be impacted by naughty test cases or
 329                 // third party routines, and cannot accept connections.
 330                 //
 331                 // Just ignore the test if the connection cannot be
 332                 // established.
 333                 System.out.println(
 334                         "Cannot make a connection in 15 seconds. " +
 335                         "Ignore in client side.");
 336                 return;
 337             }
 338 
 339             // OK, here the client and server get connected.
 340 
 341             // Signal the server, the client is ready to communicate.
 342             clientCondition.countDown();
 343 
 344             // There is still a chance in theory that the server thread may
 345             // wait client-ready timeout and then quit.  The chance should
 346             // be really rare so we don't consider it until it becomes a
 347             // real problem.
 348 
 349             // Run the application in client side.
 350             runClientApplication(sslSocket);
 351         }
 352     }
 353 
 354     /*
 355      * =============================================
 356      * Stuffs to customize the SSLContext instances.
 357      */
 358 
 359     /*
 360      * =======================================
 361      * Certificates and keys used in the test.
 362      */
 363     // Trusted certificates.
 364     private final static String[] trustedCertStrs = {
 365         // SHA256withECDSA, curve prime256v1
 366         // Validity
 367         //     Not Before: May 22 07:18:16 2018 GMT
 368         //     Not After : May 17 07:18:16 2038 GMT
 369         // Subject Key Identifier:
 370         //     60:CF:BD:73:FF:FA:1A:30:D2:A4:EC:D3:49:71:46:EF:1A:35:A0:86
 371         "-----BEGIN CERTIFICATE-----\n" +
 372         "MIIBvjCCAWOgAwIBAgIJAIvFG6GbTroCMAoGCCqGSM49BAMCMDsxCzAJBgNVBAYT\n" +
 373         "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" +
 374         "ZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMDsxCzAJBgNVBAYTAlVT\n" +
 375         "MQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZjZTBZ\n" +
 376         "MBMGByqGSM49AgEGCCqGSM49AwEHA0IABBz1WeVb6gM2mh85z3QlvaB/l11b5h0v\n" +
 377         "LIzmkC3DKlVukZT+ltH2Eq1oEkpXuf7QmbM0ibrUgtjsWH3mULfmcWmjUDBOMB0G\n" +
 378         "A1UdDgQWBBRgz71z//oaMNKk7NNJcUbvGjWghjAfBgNVHSMEGDAWgBRgz71z//oa\n" +
 379         "MNKk7NNJcUbvGjWghjAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0kAMEYCIQCG\n" +
 380         "6wluh1r2/T6L31mZXRKf9JxeSf9pIzoLj+8xQeUChQIhAJ09wAi1kV8yePLh2FD9\n" +
 381         "2YEHlSQUAbwwqCDEVB5KxaqP\n" +
 382         "-----END CERTIFICATE-----",
 383         // -----BEGIN PRIVATE KEY-----
 384         // MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg/HcHdoLJCdq3haVd
 385         // XZTSKP00YzM3xX97l98vGL/RI1KhRANCAAQc9VnlW+oDNpofOc90Jb2gf5ddW+Yd
 386         // LyyM5pAtwypVbpGU/pbR9hKtaBJKV7n+0JmzNIm61ILY7Fh95lC35nFp
 387         // -----END PRIVATE KEY-----
 388 
 389         // SHA256withRSA, 2048 bits
 390         // Validity
 391         //     Not Before: May 22 07:18:16 2018 GMT
 392         //     Not After : May 17 07:18:16 2038 GMT
 393         // Subject Key Identifier:
 394         //     0D:DD:93:C9:FE:4B:BD:35:B7:E8:99:78:90:FB:DB:5A:3D:DB:15:4C
 395         "-----BEGIN CERTIFICATE-----\n" +
 396         "MIIDSTCCAjGgAwIBAgIJAI4ZF3iy8zG+MA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNV\n" +
 397         "BAYTAlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2Vy\n" +
 398         "aXZjZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMDsxCzAJBgNVBAYT\n" +
 399         "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" +
 400         "ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALpMcY7aWieXDEM1/YJf\n" +
 401         "JW27b4nRIFZyEYhEloyGsKTuQiiQjc8cqRZFNXe2vwziDB4IyTEl0Hjl5QF6ZaQE\n" +
 402         "huPzzwvQm1pv64KrRXrmj3FisQK8B5OWLty9xp6xDqsaMRoyObLK+oIb20T5fSlE\n" +
 403         "evmo1vYjnh8CX0Yzx5Gr5ye6YSEHQvYOWEws8ad17OlyToR2KMeC8w4qo6rs59pW\n" +
 404         "g7Mxn9vo22ImDzrtAbTbXbCias3xlE0Bp0h5luyf+5U4UgksoL9B9r2oP4GrLNEV\n" +
 405         "oJk57t8lwaR0upiv3CnS8LcJELpegZub5ggqLY8ZPYFQPjlK6IzLOm6rXPgZiZ3m\n" +
 406         "RL0CAwEAAaNQME4wHQYDVR0OBBYEFA3dk8n+S701t+iZeJD721o92xVMMB8GA1Ud\n" +
 407         "IwQYMBaAFA3dk8n+S701t+iZeJD721o92xVMMAwGA1UdEwQFMAMBAf8wDQYJKoZI\n" +
 408         "hvcNAQELBQADggEBAJTRC3rKUUhVH07/1+stUungSYgpM08dY4utJq0BDk36BbmO\n" +
 409         "0AnLDMbkwFdHEoqF6hQIfpm7SQTmXk0Fss6Eejm8ynYr6+EXiRAsaXOGOBCzF918\n" +
 410         "/RuKOzqABfgSU4UBKECLM5bMfQTL60qx+HdbdVIpnikHZOFfmjCDVxoHsGyXc1LW\n" +
 411         "Jhkht8IGOgc4PMGvyzTtRFjz01kvrVQZ75aN2E0GQv6dCxaEY0i3ypSzjUWAKqDh\n" +
 412         "3e2OLwUSvumcdaxyCdZAOUsN6pDBQ+8VRG7KxnlRlY1SMEk46QgQYLbPDe/+W/yH\n" +
 413         "ca4PejicPeh+9xRAwoTpiE2gulfT7Lm+fVM7Ruc=\n" +
 414         "-----END CERTIFICATE-----",
 415         // -----BEGIN PRIVATE KEY-----
 416         // MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC6THGO2lonlwxD
 417         // Nf2CXyVtu2+J0SBWchGIRJaMhrCk7kIokI3PHKkWRTV3tr8M4gweCMkxJdB45eUB
 418         // emWkBIbj888L0Jtab+uCq0V65o9xYrECvAeTli7cvcaesQ6rGjEaMjmyyvqCG9tE
 419         // +X0pRHr5qNb2I54fAl9GM8eRq+cnumEhB0L2DlhMLPGndezpck6EdijHgvMOKqOq
 420         // 7OfaVoOzMZ/b6NtiJg867QG0212womrN8ZRNAadIeZbsn/uVOFIJLKC/Qfa9qD+B
 421         // qyzRFaCZOe7fJcGkdLqYr9wp0vC3CRC6XoGbm+YIKi2PGT2BUD45SuiMyzpuq1z4
 422         // GYmd5kS9AgMBAAECggEAFHSoU2MuWwJ+2jJnb5U66t2V1bAcuOE1g5zkWvG/G5z9
 423         // rq6Qo5kmB8f5ovdx6tw3MGUOklLwnRXBG3RxDJ1iokz3AvkY1clMNsDPlDsUrQKF
 424         // JSO4QUBQTPSZhnsyfR8XHSU+qJ8Y+ohMfzpVv95BEoCzebtXdVgxVegBlcEmVHo2
 425         // kMmkRN+bYNsr8eb2r+b0EpyumS39ZgKYh09+cFb78y3T6IFMGcVJTP6nlGBFkmA/
 426         // 25pYeCF2tSki08qtMJZQAvKfw0Kviibk7ZxRbJqmc7B1yfnOEHP6ftjuvKl2+RP/
 427         // +5P5f8CfIP6gtA0LwSzAqQX/hfIKrGV5j0pCqrD0kQKBgQDeNR6Xi4sXVq79lihO
 428         // a1bSeV7r8yoQrS8x951uO+ox+UIZ1MsAULadl7zB/P0er92p198I9M/0Jth3KBuS
 429         // zj45mucvpiiGvmQlMKMEfNq4nN7WHOu55kufPswQB2mR4J3xmwI+4fM/nl1zc82h
 430         // De8JSazRldJXNhfx0RGFPmgzbwKBgQDWoVXrXLbCAn41oVnWB8vwY9wjt92ztDqJ
 431         // HMFA/SUohjePep9UDq6ooHyAf/Lz6oE5NgeVpPfTDkgvrCFVKnaWdwALbYoKXT2W
 432         // 9FlyJox6eQzrtHAacj3HJooXWuXlphKSizntfxj3LtMR9BmrmRJOfK+SxNOVJzW2
 433         // +MowT20EkwKBgHmpB8jdZBgxI7o//m2BI5Y1UZ1KE5vx1kc7VXzHXSBjYqeV9FeF
 434         // 2ZZLP9POWh/1Fh4pzTmwIDODGT2UPhSQy0zq3O0fwkyT7WzXRknsuiwd53u/dejg
 435         // iEL2NPAJvulZ2+AuiHo5Z99LK8tMeidV46xoJDDUIMgTG+UQHNGhK5gNAoGAZn/S
 436         // Cn7SgMC0CWSvBHnguULXZO9wH1wZAFYNLL44OqwuaIUFBh2k578M9kkke7woTmwx
 437         // HxQTjmWpr6qimIuY6q6WBN8hJ2Xz/d1fwhYKzIp20zHuv5KDUlJjbFfqpsuy3u1C
 438         // kts5zwI7pr1ObRbDGVyOdKcu7HI3QtR5qqyjwaUCgYABo7Wq6oHva/9V34+G3Goh
 439         // 63bYGUnRw2l5BD11yhQv8XzGGZFqZVincD8gltNThB0Dc/BI+qu3ky4YdgdZJZ7K
 440         // z51GQGtaHEbrHS5caV79yQ8QGY5mUVH3E+VXSxuIqb6pZq2DH4sTAEFHyncddmOH
 441         // zoXBInYwRG9KE/Bw5elhUw==
 442         // -----END PRIVATE KEY-----
 443 
 444         // SHA256withDSA, 2048 bits
 445         // Validity
 446         //     Not Before: May 22 07:18:18 2018 GMT
 447         //     Not After : May 17 07:18:18 2038 GMT
 448         // Subject Key Identifier:
 449         //     76:66:9E:F7:3B:DD:45:E5:3B:D9:72:3C:3F:F0:54:39:86:31:26:53
 450         "-----BEGIN CERTIFICATE-----\n" +
 451         "MIIErjCCBFSgAwIBAgIJAOktYLNCbr02MAsGCWCGSAFlAwQDAjA7MQswCQYDVQQG\n" +
 452         "EwJVUzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2\n" +
 453         "Y2UwHhcNMTgwNTIyMDcxODE4WhcNMzgwNTE3MDcxODE4WjA7MQswCQYDVQQGEwJV\n" +
 454         "UzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2Y2Uw\n" +
 455         "ggNHMIICOQYHKoZIzjgEATCCAiwCggEBAO5GyPhSm0ze3LSu+gicdULLj05iOfTL\n" +
 456         "UvZQ29sYz41zmqrLBQbdKiHqgJu2Re9sgTb5suLNjF047TOLPnU3jhPtWm2X8Xzi\n" +
 457         "VGIcHym/Q/MeZxStt/88seqroI3WOKzIML2GcrishT+lcGrtH36Tf1+ue2Snn3PS\n" +
 458         "WyxygNqPjllP5uUjYmFLvAf4QLMldkd/D2VxcwsHjB8y5iUZsXezc/LEhRZS/02m\n" +
 459         "ivqlRw3AMkq/OVe/ZtxFWsP0nsfxEGdZuaUFpppGfixxFvymrB3+J51cTt+pZBDq\n" +
 460         "D2y0DYfc+88iCs4jwHTfcDIpLb538HBjBj2rEgtQESQmB0ooD/+wsPsCIQC1bYch\n" +
 461         "gElNtDYL3FgpLgNSUYp7gIWv9ehaC7LO2z7biQKCAQBitvFOnDkUja8NAF7lDpOV\n" +
 462         "b5ipQ8SicBLW3kQamxhyuyxgZyy/PojZ/oPorkqW/T/A0rhnG6MssEpAtdiwVB+c\n" +
 463         "rBYGo3bcwmExJhdOJ6dYuKFppPWhCwKMHs9npK+lqBMl8l5j58xlcFeC7ZfGf8GY\n" +
 464         "GkhFW0c44vEQhMMbac6ZTTP4mw+1t7xJfmDMlLEyIpTXaAAk8uoVLWzQWnR40sHi\n" +
 465         "ybvS0u3JxQkb7/y8tOOZu8qlz/YOS7lQ6UxUGX27Ce1E0+agfPphetoRAlS1cezq\n" +
 466         "Wa7r64Ga0nkj1kwkcRqjgTiJx0NwnUXr78VAXFhVF95+O3lfqhvdtEGtkhDGPg7N\n" +
 467         "A4IBBgACggEBAMmSHQK0w2i+iqUjOPzn0yNEZrzepLlLeQ1tqtn0xnlv5vBAeefD\n" +
 468         "Pm9dd3tZOjufVWP7hhEz8xPobb1CS4e3vuQiv5UBfhdPL3f3l9T7JMAKPH6C9Vve\n" +
 469         "OQXE5eGqbjsySbcmseHoYUt1WCSnSda1opX8zchX04e7DhGfE2/L9flpYEoSt8lI\n" +
 470         "vMNjgOwvKdW3yvPt1/eBBHYNFG5gWPv/Q5KoyCtHS03uqGm4rNc/wZTIEEfd66C+\n" +
 471         "QRaUltjOaHmtwOdDHaNqwhYZSVOip+Mo+TfyzHFREcdHLapo7ZXqbdYkRGxRR3d+\n" +
 472         "3DfHaraJO0OKoYlPkr3JMvM/MSGR9AnZOcejUDBOMB0GA1UdDgQWBBR2Zp73O91F\n" +
 473         "5TvZcjw/8FQ5hjEmUzAfBgNVHSMEGDAWgBR2Zp73O91F5TvZcjw/8FQ5hjEmUzAM\n" +
 474         "BgNVHRMEBTADAQH/MAsGCWCGSAFlAwQDAgNHADBEAiBzriYE41M2y9Hy5ppkL0Qn\n" +
 475         "dIlNc8JhXT/PHW7GDtViagIgMko8Qoj9gDGPK3+O9E8DC3wGiiF9CObM4LN387ok\n" +
 476         "J+g=\n" +
 477         "-----END CERTIFICATE-----"
 478         // -----BEGIN PRIVATE KEY-----
 479         // MIICZQIBADCCAjkGByqGSM44BAEwggIsAoIBAQDuRsj4UptM3ty0rvoInHVCy49O
 480         // Yjn0y1L2UNvbGM+Nc5qqywUG3Soh6oCbtkXvbIE2+bLizYxdOO0ziz51N44T7Vpt
 481         // l/F84lRiHB8pv0PzHmcUrbf/PLHqq6CN1jisyDC9hnK4rIU/pXBq7R9+k39frntk
 482         // p59z0lsscoDaj45ZT+blI2JhS7wH+ECzJXZHfw9lcXMLB4wfMuYlGbF3s3PyxIUW
 483         // Uv9Npor6pUcNwDJKvzlXv2bcRVrD9J7H8RBnWbmlBaaaRn4scRb8pqwd/iedXE7f
 484         // qWQQ6g9stA2H3PvPIgrOI8B033AyKS2+d/BwYwY9qxILUBEkJgdKKA//sLD7AiEA
 485         // tW2HIYBJTbQ2C9xYKS4DUlGKe4CFr/XoWguyzts+24kCggEAYrbxTpw5FI2vDQBe
 486         // 5Q6TlW+YqUPEonAS1t5EGpsYcrssYGcsvz6I2f6D6K5Klv0/wNK4ZxujLLBKQLXY
 487         // sFQfnKwWBqN23MJhMSYXTienWLihaaT1oQsCjB7PZ6SvpagTJfJeY+fMZXBXgu2X
 488         // xn/BmBpIRVtHOOLxEITDG2nOmU0z+JsPtbe8SX5gzJSxMiKU12gAJPLqFS1s0Fp0
 489         // eNLB4sm70tLtycUJG+/8vLTjmbvKpc/2Dku5UOlMVBl9uwntRNPmoHz6YXraEQJU
 490         // tXHs6lmu6+uBmtJ5I9ZMJHEao4E4icdDcJ1F6+/FQFxYVRfefjt5X6ob3bRBrZIQ
 491         // xj4OzQQjAiEAsceWOM8do4etxp2zgnoNXV8PUUyqWhz1+0srcKV7FR4=
 492         // -----END PRIVATE KEY-----
 493         };
 494 
 495     // End entity certificate.
 496     private final static String[] endEntityCertStrs = {
 497         // SHA256withECDSA, curve prime256v1
 498         // Validity
 499         //     Not Before: May 22 07:18:16 2018 GMT
 500         //     Not After : May 17 07:18:16 2038 GMT
 501         // Authority Key Identifier:
 502         //     60:CF:BD:73:FF:FA:1A:30:D2:A4:EC:D3:49:71:46:EF:1A:35:A0:86
 503         "-----BEGIN CERTIFICATE-----\n" +
 504         "MIIBqjCCAVCgAwIBAgIJAPLY8qZjgNRAMAoGCCqGSM49BAMCMDsxCzAJBgNVBAYT\n" +
 505         "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" +
 506         "ZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMFUxCzAJBgNVBAYTAlVT\n" +
 507         "MQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZjZTEY\n" +
 508         "MBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD\n" +
 509         "QgAEb+9n05qfXnfHUb0xtQJNS4JeSi6IjOfW5NqchvKnfJey9VkJzR7QHLuOESdf\n" +
 510         "xlR7q8YIWgih3iWLGfB+wxHiOqMjMCEwHwYDVR0jBBgwFoAUYM+9c//6GjDSpOzT\n" +
 511         "SXFG7xo1oIYwCgYIKoZIzj0EAwIDSAAwRQIgWpRegWXMheiD3qFdd8kMdrkLxRbq\n" +
 512         "1zj8nQMEwFTUjjQCIQDRIrAjZX+YXHN9b0SoWWLPUq0HmiFIi8RwMnO//wJIGQ==\n" +
 513         "-----END CERTIFICATE-----",
 514 
 515         // SHA256withRSA, 2048 bits
 516         // Validity
 517         //     Not Before: May 22 07:18:16 2018 GMT
 518         //     Not After : May 17 07:18:16 2038 GMT
 519         // Authority Key Identifier:
 520         //     0D:DD:93:C9:FE:4B:BD:35:B7:E8:99:78:90:FB:DB:5A:3D:DB:15:4C
 521         "-----BEGIN CERTIFICATE-----\n" +
 522         "MIIDNjCCAh6gAwIBAgIJAO2+yPcFryUTMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNV\n" +
 523         "BAYTAlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2Vy\n" +
 524         "aXZjZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMFUxCzAJBgNVBAYT\n" +
 525         "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" +
 526         "ZTEYMBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOC\n" +
 527         "AQ8AMIIBCgKCAQEAszfBobWfZIp8AgC6PiWDDavP65mSvgCXUGxACbxVNAfkLhNR\n" +
 528         "QOsHriRB3X1Q3nvO9PetC6wKlvE9jlnDDj7D+1j1r1CHO7ms1fq8rfcQYdkanDtu\n" +
 529         "4AlHo8v+SSWX16MIXFRYDj2VVHmyPtgbltcg4zGAuwT746FdLI94uXjJjq1IOr/v\n" +
 530         "0VIlwE5ORWH5Xc+5Tj+oFWK0E4a4GHDgtKKhn2m72hN56/GkPKGkguP5NRS1qYYV\n" +
 531         "/EFkdyQMOV8J1M7HaicSft4OL6eKjTrgo93+kHk+tv0Dc6cpVBnalX3TorG8QI6B\n" +
 532         "cHj1XQd78oAlAC+/jF4pc0mwi0un49kdK9gRfQIDAQABoyMwITAfBgNVHSMEGDAW\n" +
 533         "gBQN3ZPJ/ku9NbfomXiQ+9taPdsVTDANBgkqhkiG9w0BAQsFAAOCAQEApXS0nKwm\n" +
 534         "Kp8gpmO2yG1rpd1+2wBABiMU4JZaTqmma24DQ3RzyS+V2TeRb29dl5oTUEm98uc0\n" +
 535         "GPZvhK8z5RFr4YE17dc04nI/VaNDCw4y1NALXGs+AHkjoPjLyGbWpi1S+gfq2sNB\n" +
 536         "Ekkjp6COb/cb9yiFXOGVls7UOIjnVZVd0r7KaPFjZhYh82/f4PA/A1SnIKd1+nfH\n" +
 537         "2yk7mSJNC7Z3qIVDL8MM/jBVwiC3uNe5GPB2uwhd7k5LGAVN3j4HQQGB0Sz+VC1h\n" +
 538         "92oi6xDa+YBva2fvHuCd8P50DDjxmp9CemC7rnZ5j8egj88w14X44Xjb/Fd/ApG9\n" +
 539         "e57NnbT7KM+Grw==\n" +
 540         "-----END CERTIFICATE-----",
 541 
 542         // SHA256withRSA, curv prime256v1
 543         // Validity
 544         //     Not Before: May 22 07:18:16 2018 GMT
 545         //     Not After : May 21 07:18:16 2028 GMT
 546         // Authority Key Identifier:
 547         //     0D:DD:93:C9:FE:4B:BD:35:B7:E8:99:78:90:FB:DB:5A:3D:DB:15:4C
 548         "-----BEGIN CERTIFICATE-----\n" +
 549         "MIICazCCAVOgAwIBAgIJAO2+yPcFryUUMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNV\n" +
 550         "BAYTAlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2Vy\n" +
 551         "aXZjZTAeFw0xODA1MjIwNzE4MTZaFw0yODA1MjEwNzE4MTZaMFUxCzAJBgNVBAYT\n" +
 552         "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" +
 553         "ZTEYMBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0D\n" +
 554         "AQcDQgAE59MERNTlVZ1eeps8Z3Oue5ZkgQdPtD+WIE6tj3PbIKpxGPDxvfNP959A\n" +
 555         "yQjEK/ehWQVrCMmNoEkIzY+IIBgB06MjMCEwHwYDVR0jBBgwFoAUDd2Tyf5LvTW3\n" +
 556         "6Jl4kPvbWj3bFUwwDQYJKoZIhvcNAQELBQADggEBAFOTVEqs70ykhZiIdrEsF1Ra\n" +
 557         "I3B2rLvwXZk52uSltk2/bzVvewA577ZCoxQ1pL7ynkisPfBN1uVYtHjM1VA3RC+4\n" +
 558         "+TAK78dnI7otYjWoHp5rvs4l6c/IbOspS290IlNuDUxMErEm5wxIwj+Aukx/1y68\n" +
 559         "hOyCvHBLMY2c1LskH1MMBbDuS1aI+lnGpToi+MoYObxGcV458vxuT8+wwV8Fkpvd\n" +
 560         "ll8IIFmeNPRv+1E+lXbES6CSNCVaZ/lFhPgdgYKleN7sfspiz50DG4dqafuEAaX5\n" +
 561         "xaK1NWXJxTRz0ROH/IUziyuDW6jphrlgit4+3NCzp6vP9hAJQ8Vhcj0n15BKHIQ=\n" +
 562         "-----END CERTIFICATE-----",
 563 
 564         // SHA256withDSA, 2048 bits
 565         // Validity
 566         //     Not Before: May 22 07:18:20 2018 GMT
 567         //     Not After : May 17 07:18:20 2038 GMT
 568         // Authority Key Identifier:
 569         //     76:66:9E:F7:3B:DD:45:E5:3B:D9:72:3C:3F:F0:54:39:86:31:26:53
 570         "-----BEGIN CERTIFICATE-----\n" +
 571         "MIIEnDCCBEGgAwIBAgIJAP/jh1qVhNVjMAsGCWCGSAFlAwQDAjA7MQswCQYDVQQG\n" +
 572         "EwJVUzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2\n" +
 573         "Y2UwHhcNMTgwNTIyMDcxODIwWhcNMzgwNTE3MDcxODIwWjBVMQswCQYDVQQGEwJV\n" +
 574         "UzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2Y2Ux\n" +
 575         "GDAWBgNVBAMMD1JlZ3Jlc3Npb24gVGVzdDCCA0cwggI6BgcqhkjOOAQBMIICLQKC\n" +
 576         "AQEAmlavgoJrMcjqWRVcDE2dmWAPREgnzQvneEDef68cprDzjSwvOs5QeFyx75ib\n" +
 577         "ado1e6jO/rW1prCGWHDD1oA/Tn4Pk3vu0nUxzvl1qATc+aJbpUU5Op0bvp6LbCsQ\n" +
 578         "QslV9FeRh7Eb7bP6gpc/kHCBzEgC1VCK7prccXWy+t6SMOHbND3h+UbckfSaUuaV\n" +
 579         "sVJNTD1D6GElfRj4Nmz1BGPfSYvKorwNZEU3gXwFgtDoAcGx7tcyClLpDHfqRfw/\n" +
 580         "7yiqLyeiP7D4hl5lMNouJWDlAdMFp0FMgS3s9VDFinIcr6VtBWMTG7+4+czHAB+3\n" +
 581         "fvrwlqNzhBn3uFHrekN/w8fNxwIhAJo7Sae1za7IMW0Q6hE5B4b+s2B/FaKPoA4E\n" +
 582         "jtZu13B9AoIBAQCOZqLMKfvqZWUgT0PQ3QjR7dAFdd06I9Y3+TOQzZk1+j+vw/6E\n" +
 583         "X4vFItX4gihb/u5Q9CdmpwhVGi7bvo+7+/IKeTgoQ6f5+PSug7SrWWUQ5sPwaZui\n" +
 584         "zXZJ5nTeZDucFc2yFx0wgnjbPwiUxZklOT7xGiOMtzOTa2koCz5KuIBL+/wPKKxm\n" +
 585         "ypo9VoY9xfbdU6LMXZv/lpD5XTM9rYHr/vUTNkukvV6Hpm0YMEWhVZKUJiqCqTqG\n" +
 586         "XHaleOxSw6uQWB/+TznifcC7gB48UOQjCqOKf5VuwQneJLhlhU/jhRV3xtr+hLZa\n" +
 587         "hW1wYhVi8cjLDrZFKlgEQqhB4crnJU0mJY+tA4IBBQACggEAID0ezl00/X8mv7eb\n" +
 588         "bzovum1+DEEP7FM57k6HZEG2N3ve4CW+0m9Cd+cWPz8wkZ+M0j/Eqa6F0IdbkXEc\n" +
 589         "Q7CuzvUyJ57xQ3L/WCgXsiS+Bh8O4Mz7GwW22CGmHqafbVv+hKBfr8MkskO6GJUt\n" +
 590         "SUF/CVLzB4gMIvZMH26tBP2xK+i7FeEK9kT+nGdzQSZBAhFYpEVCBplHZO24/OYq\n" +
 591         "1DNoU327nUuXIhmsfA8N0PjiWbIZIjTPwBGr9H0LpATI7DIDNcvRRvtROP+pBU9y\n" +
 592         "fuykPkptg9C0rCM9t06bukpOSaEz/2VIQdLE8fHYFA6pHZ6CIc2+5cfvMgTPhcjz\n" +
 593         "W2jCt6MjMCEwHwYDVR0jBBgwFoAUdmae9zvdReU72XI8P/BUOYYxJlMwCwYJYIZI\n" +
 594         "AWUDBAMCA0gAMEUCIQCeI5fN08b9BpOaHdc3zQNGjp24FOL/RxlBLeBAorswJgIg\n" +
 595         "JEZ8DhYxQy1O7mmZ2UIT7op6epWMB4dENjs0qWPmcKo=\n" +
 596         "-----END CERTIFICATE-----"
 597         };
 598 
 599     // Private key in the format of PKCS#8.
 600     private final static String[] endEntityPrivateKeys = {
 601         //
 602         // EC private key related to cert endEntityCertStrs[0].
 603         //
 604         "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgn5K03bpTLjEtFQRa\n" +
 605         "JUtx22gtmGEvvSUSQdimhGthdtihRANCAARv72fTmp9ed8dRvTG1Ak1Lgl5KLoiM\n" +
 606         "59bk2pyG8qd8l7L1WQnNHtAcu44RJ1/GVHurxghaCKHeJYsZ8H7DEeI6",
 607 
 608         //
 609         // RSA private key related to cert endEntityCertStrs[1].
 610         //
 611         "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzN8GhtZ9kinwC\n" +
 612         "ALo+JYMNq8/rmZK+AJdQbEAJvFU0B+QuE1FA6weuJEHdfVDee870960LrAqW8T2O\n" +
 613         "WcMOPsP7WPWvUIc7uazV+ryt9xBh2RqcO27gCUejy/5JJZfXowhcVFgOPZVUebI+\n" +
 614         "2BuW1yDjMYC7BPvjoV0sj3i5eMmOrUg6v+/RUiXATk5FYfldz7lOP6gVYrQThrgY\n" +
 615         "cOC0oqGfabvaE3nr8aQ8oaSC4/k1FLWphhX8QWR3JAw5XwnUzsdqJxJ+3g4vp4qN\n" +
 616         "OuCj3f6QeT62/QNzpylUGdqVfdOisbxAjoFwePVdB3vygCUAL7+MXilzSbCLS6fj\n" +
 617         "2R0r2BF9AgMBAAECggEASIkPkMCuw4WdTT44IwERus3IOIYOs2IP3BgEDyyvm4B6\n" +
 618         "JP/iihDWKfA4zEl1Gqcni1RXMHswSglXra682J4kui02Ov+vzEeJIY37Ibn2YnP5\n" +
 619         "ZjRT2s9GtI/S2o4hl8A/mQb2IMViFC+xKehTukhV4j5d6NPKk0XzLR7gcMjnYxwn\n" +
 620         "l21fS6D2oM1xRG/di7sL+uLF8EXLRzfiWDNi12uQv4nwtxPKvuKhH6yzHt7YqMH0\n" +
 621         "46pmDKDaxV4w1JdycjCb6NrCJOYZygoQobuZqOQ30UZoZsPJrtovkncFr1e+lNcO\n" +
 622         "+aWDfOLCtTH046dEQh5oCShyXMybNlry/QHsOtHOwQKBgQDh2iIjs+FPpQy7Z3EX\n" +
 623         "DGEvHYqPjrYO9an2KSRr1m9gzRlWYxKY46WmPKwjMerYtra0GP+TBHrgxsfO8tD2\n" +
 624         "wUAII6sd1qup0a/Sutgf2JxVilLykd0+Ge4/Cs51tCdJ8EqDV2B6WhTewOY2EGvg\n" +
 625         "JiKYkeNwgRX/9M9CFSAMAk0hUQKBgQDLJAartL3DoGUPjYtpJnfgGM23yAGl6G5r\n" +
 626         "NSXDn80BiYIC1p0bG3N0xm3yAjqOtJAUj9jZbvDNbCe3GJfLARMr23legX4tRrgZ\n" +
 627         "nEdKnAFKAKL01oM+A5/lHdkwaZI9yyv+hgSVdYzUjB8rDmzeVQzo1BT7vXypt2yV\n" +
 628         "6O1OnUpCbQKBgA/0rzDChopv6KRcvHqaX0tK1P0rYeVQqb9ATNhpf9jg5Idb3HZ8\n" +
 629         "rrk91BNwdVz2G5ZBpdynFl9G69rNAMJOCM4KZw5mmh4XOEq09Ivba8AHU7DbaTv3\n" +
 630         "7QL7KnbaUWRB26HHzIMYVh0el6T+KADf8NXCiMTr+bfpfbL3dxoiF3zhAoGAbCJD\n" +
 631         "Qse1dBs/cKYCHfkSOsI5T6kx52Tw0jS6Y4X/FOBjyqr/elyEexbdk8PH9Ar931Qr\n" +
 632         "NKMvn8oA4iA/PRrXX7M2yi3YQrWwbkGYWYjtzrzEAdzmg+5eARKAeJrZ8/bg9l3U\n" +
 633         "ttKaItJsDPlizn8rngy3FsJpR9aSAMK6/+wOiYkCgYEA1tZkI1rD1W9NYZtbI9BE\n" +
 634         "qlJVFi2PBOJMKNuWdouPX3HLQ72GJSQff2BFzLTELjweVVJ0SvY4IipzpQOHQOBy\n" +
 635         "5qh/p6izXJZh3IHtvwVBjHoEVplg1b2+I5e3jDCfqnwcQw82dW5SxOJMg1h/BD0I\n" +
 636         "qAL3go42DYeYhu/WnECMeis=",
 637 
 638         //
 639         // EC private key related to cert endEntityCertStrs[2].
 640         //
 641         "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgGVc7hICpmp91jbYe\n" +
 642         "nrr8nYHD37RZP3VENY+szuA7WjuhRANCAATn0wRE1OVVnV56mzxnc657lmSBB0+0\n" +
 643         "P5YgTq2Pc9sgqnEY8PG980/3n0DJCMQr96FZBWsIyY2gSQjNj4ggGAHT",
 644 
 645         //
 646         // DSA private key related to cert endEntityCertStrs[3].
 647         //
 648         "MIICZQIBADCCAjoGByqGSM44BAEwggItAoIBAQCaVq+CgmsxyOpZFVwMTZ2ZYA9E\n" +
 649         "SCfNC+d4QN5/rxymsPONLC86zlB4XLHvmJtp2jV7qM7+tbWmsIZYcMPWgD9Ofg+T\n" +
 650         "e+7SdTHO+XWoBNz5olulRTk6nRu+notsKxBCyVX0V5GHsRvts/qClz+QcIHMSALV\n" +
 651         "UIrumtxxdbL63pIw4ds0PeH5RtyR9JpS5pWxUk1MPUPoYSV9GPg2bPUEY99Ji8qi\n" +
 652         "vA1kRTeBfAWC0OgBwbHu1zIKUukMd+pF/D/vKKovJ6I/sPiGXmUw2i4lYOUB0wWn\n" +
 653         "QUyBLez1UMWKchyvpW0FYxMbv7j5zMcAH7d++vCWo3OEGfe4Uet6Q3/Dx83HAiEA\n" +
 654         "mjtJp7XNrsgxbRDqETkHhv6zYH8Voo+gDgSO1m7XcH0CggEBAI5moswp++plZSBP\n" +
 655         "Q9DdCNHt0AV13Toj1jf5M5DNmTX6P6/D/oRfi8Ui1fiCKFv+7lD0J2anCFUaLtu+\n" +
 656         "j7v78gp5OChDp/n49K6DtKtZZRDmw/Bpm6LNdknmdN5kO5wVzbIXHTCCeNs/CJTF\n" +
 657         "mSU5PvEaI4y3M5NraSgLPkq4gEv7/A8orGbKmj1Whj3F9t1Tosxdm/+WkPldMz2t\n" +
 658         "gev+9RM2S6S9XoembRgwRaFVkpQmKoKpOoZcdqV47FLDq5BYH/5POeJ9wLuAHjxQ\n" +
 659         "5CMKo4p/lW7BCd4kuGWFT+OFFXfG2v6EtlqFbXBiFWLxyMsOtkUqWARCqEHhyucl\n" +
 660         "TSYlj60EIgIgLfA75+8KcKxdN8mr6gzGjQe7jPFGG42Ejhd7Q2F4wuw="
 661         };
 662 
 663     // Private key algorithm of endEntityPrivateKeys.
 664     private final static String[] endEntityPrivateKeyAlgs = {
 665         "EC",
 666         "RSA",
 667         "EC",
 668         "DSA",
 669         };
 670 
 671     // Private key names of endEntityPrivateKeys.
 672     private final static String[] endEntityPrivateKeyNames = {
 673         "ecdsa",
 674         "rsa",
 675         "ec-rsa",
 676         "dsa",
 677         };
 678 
 679     /*
 680      * Create an instance of SSLContext with the specified trust/key materials.
 681      */
 682     private SSLContext createSSLContext(
 683             String[] trustedMaterials,
 684             String[] keyMaterialCerts,
 685             String[] keyMaterialKeys,
 686             String[] keyMaterialKeyAlgs,
 687             String[] keyMaterialKeyNames,
 688             ContextParameters params) throws Exception {
 689 
 690         KeyStore ts = null;     // trust store
 691         KeyStore ks = null;     // key store
 692         char passphrase[] = "passphrase".toCharArray();
 693 
 694         // Generate certificate from cert string.
 695         CertificateFactory cf = CertificateFactory.getInstance("X.509");
 696 
 697         // Import the trused certs.
 698         ByteArrayInputStream is;
 699         if (trustedMaterials != null && trustedMaterials.length != 0) {
 700             ts = KeyStore.getInstance("JKS");
 701             ts.load(null, null);
 702 
 703             Certificate[] trustedCert =
 704                     new Certificate[trustedMaterials.length];
 705             for (int i = 0; i < trustedMaterials.length; i++) {
 706                 String trustedCertStr = trustedMaterials[i];
 707 
 708                 is = new ByteArrayInputStream(trustedCertStr.getBytes());
 709                 try {
 710                     trustedCert[i] = cf.generateCertificate(is);
 711                 } finally {
 712                     is.close();
 713                 }
 714 
 715                 ts.setCertificateEntry("trusted-cert-" + i, trustedCert[i]);
 716             }
 717         }
 718 
 719         // Import the key materials.
 720         //
 721         // Note that certification pathes bigger than one are not supported yet.
 722         boolean hasKeyMaterials =
 723             (keyMaterialCerts != null) && (keyMaterialCerts.length != 0) &&
 724             (keyMaterialKeys != null) && (keyMaterialKeys.length != 0) &&
 725             (keyMaterialKeyAlgs != null) && (keyMaterialKeyAlgs.length != 0) &&
 726             (keyMaterialCerts.length == keyMaterialKeys.length) &&
 727             (keyMaterialCerts.length == keyMaterialKeyAlgs.length);
 728         if (hasKeyMaterials) {
 729             ks = KeyStore.getInstance("JKS");
 730             ks.load(null, null);
 731 
 732             for (int i = 0; i < keyMaterialCerts.length; i++) {
 733                 String keyCertStr = keyMaterialCerts[i];
 734 
 735                 // generate the private key.
 736                 PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
 737                     Base64.getMimeDecoder().decode(keyMaterialKeys[i]));
 738                 KeyFactory kf =
 739                     KeyFactory.getInstance(keyMaterialKeyAlgs[i]);
 740                 PrivateKey priKey = kf.generatePrivate(priKeySpec);
 741 
 742                 // generate certificate chain
 743                 is = new ByteArrayInputStream(keyCertStr.getBytes());
 744                 Certificate keyCert = null;
 745                 try {
 746                     keyCert = cf.generateCertificate(is);
 747                 } finally {
 748                     is.close();
 749                 }
 750 
 751                 Certificate[] chain = new Certificate[] { keyCert };
 752 
 753                 // import the key entry.
 754                 ks.setKeyEntry("cert-" + keyMaterialKeyNames[i],
 755                         priKey, passphrase, chain);
 756             }
 757         }
 758 
 759         // Create an SSLContext object.
 760         TrustManagerFactory tmf =
 761                 TrustManagerFactory.getInstance(params.tmAlgorithm);
 762         tmf.init(ts);
 763 
 764         SSLContext context = SSLContext.getInstance(params.contextProtocol);
 765         if (hasKeyMaterials && ks != null) {
 766             KeyManagerFactory kmf =
 767                     KeyManagerFactory.getInstance(params.kmAlgorithm);
 768             kmf.init(ks, passphrase);
 769 
 770             context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
 771         } else {
 772             context.init(null, tmf.getTrustManagers(), null);
 773         }
 774 
 775         return context;
 776     }
 777 
 778     /*
 779      * =================================================
 780      * Stuffs to boot up the client-server mode testing.
 781      */
 782     private Thread clientThread = null;
 783     private Thread serverThread = null;
 784     private volatile Exception serverException = null;
 785     private volatile Exception clientException = null;
 786 
 787     /*
 788      * Should we run the client or server in a separate thread?
 789      * Both sides can throw exceptions, but do you have a preference
 790      * as to which side should be the main thread.
 791      */
 792     private static final boolean separateServerThread = false;
 793 
 794     /*
 795      * Boot up the testing, used to drive remainder of the test.
 796      */
 797     private void bootup() throws Exception {
 798         Exception startException = null;
 799         try {
 800             if (separateServerThread) {
 801                 startServer(true);
 802                 startClient(false);
 803             } else {
 804                 startClient(true);
 805                 startServer(false);
 806             }
 807         } catch (Exception e) {
 808             startException = e;
 809         }
 810 
 811         /*
 812          * Wait for other side to close down.
 813          */
 814         if (separateServerThread) {
 815             if (serverThread != null) {
 816                 serverThread.join();
 817             }
 818         } else {
 819             if (clientThread != null) {
 820                 clientThread.join();
 821             }
 822         }
 823 
 824         /*
 825          * When we get here, the test is pretty much over.
 826          * Which side threw the error?
 827          */
 828         Exception local;
 829         Exception remote;
 830 
 831         if (separateServerThread) {
 832             remote = serverException;
 833             local = clientException;
 834         } else {
 835             remote = clientException;
 836             local = serverException;
 837         }
 838 
 839         Exception exception = null;
 840 
 841         /*
 842          * Check various exception conditions.
 843          */
 844         if ((local != null) && (remote != null)) {
 845             // If both failed, return the curthread's exception.
 846             local.initCause(remote);
 847             exception = local;
 848         } else if (local != null) {
 849             exception = local;
 850         } else if (remote != null) {
 851             exception = remote;
 852         } else if (startException != null) {
 853             exception = startException;
 854         }
 855 
 856         /*
 857          * If there was an exception *AND* a startException,
 858          * output it.
 859          */
 860         if (exception != null) {
 861             if (exception != startException && startException != null) {
 862                 exception.addSuppressed(startException);
 863             }
 864             throw exception;
 865         }
 866 
 867         // Fall-through: no exception to throw!
 868     }
 869 
 870     private void startServer(boolean newThread) throws Exception {
 871         if (newThread) {
 872             serverThread = new Thread() {
 873                 @Override
 874                 public void run() {
 875                     try {
 876                         doServerSide();
 877                     } catch (Exception e) {
 878                         /*
 879                          * Our server thread just died.
 880                          *
 881                          * Release the client, if not active already...
 882                          */
 883                         logException("Server died", e);
 884                         serverException = e;
 885                     }
 886                 }
 887             };
 888             serverThread.start();
 889         } else {
 890             try {
 891                 doServerSide();
 892             } catch (Exception e) {
 893                 logException("Server failed", e);
 894                 serverException = e;
 895             }
 896         }
 897     }
 898 
 899     private void startClient(boolean newThread) throws Exception {
 900         if (newThread) {
 901             clientThread = new Thread() {
 902                 @Override
 903                 public void run() {
 904                     try {
 905                         doClientSide();
 906                     } catch (Exception e) {
 907                         /*
 908                          * Our client thread just died.
 909                          */
 910                         logException("Client died", e);
 911                         clientException = e;
 912                     }
 913                 }
 914             };
 915             clientThread.start();
 916         } else {
 917             try {
 918                 doClientSide();
 919             } catch (Exception e) {
 920                 logException("Client failed", e);
 921                 clientException = e;
 922             }
 923         }
 924     }
 925 
 926     private synchronized void logException(String prefix, Throwable cause) {
 927         System.out.println(prefix + ": " + cause);
 928         cause.printStackTrace(System.out);
 929     }
 930 }