TestSSLContext.java revision f33eae7e84eb6d3b0f4e86b59605bb3de73009f3
1bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom/* 2bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Copyright (C) 2010 The Android Open Source Project 3bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * 4bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License"); 5bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * you may not use this file except in compliance with the License. 6bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * You may obtain a copy of the License at 7bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * 8bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * http://www.apache.org/licenses/LICENSE-2.0 9bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * 10bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Unless required by applicable law or agreed to in writing, software 11bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS, 12bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * See the License for the specific language governing permissions and 14bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * limitations under the License. 15bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 16bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 17bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrompackage javax.net.ssl; 18bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 19bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport java.math.BigInteger; 20bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport java.net.InetAddress; 21bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport java.net.InetSocketAddress; 22bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport java.security.KeyPair; 23bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport java.security.KeyPairGenerator; 24bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport java.security.KeyStore; 25bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport java.security.SecureRandom; 26bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport java.security.Security; 27e688a4123f165ed2905878e312b074b8c825d119Brian Carlstromimport java.security.cert.Certificate; 28bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport java.security.cert.X509Certificate; 29bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport java.security.interfaces.RSAPrivateKey; 30bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport java.security.interfaces.RSAPublicKey; 31bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport java.util.Date; 32bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport java.util.Hashtable; 33bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport org.bouncycastle.jce.X509Principal; 34bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport org.bouncycastle.jce.provider.BouncyCastleProvider; 35bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport org.bouncycastle.x509.X509V3CertificateGenerator; 36bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 37bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom/** 38bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * TestSSLContext is a convenience class for other tests that 39bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * want a canned SSLContext and related state for testing so they 40bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * don't have to duplicate the logic. 41bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 42bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrompublic final class TestSSLContext { 43bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 44bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public static final boolean IS_RI = !"Dalvik Core Library".equals(System.getProperty("java.specification.name")); 45bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public static final String PROVIDER_NAME = (IS_RI) ? "SunJSSE" : "HarmonyJSSE"; 46bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 47f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes /* 480af0a7959d838c48e6b4e8dc9ac188ff6bbb6a87Brian Carlstrom * The RI and Android have very different default SSLSession cache behaviors. 490af0a7959d838c48e6b4e8dc9ac188ff6bbb6a87Brian Carlstrom * The RI keeps an unlimited number of SSLSesions around for 1 day. 50f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * Android keeps 10 SSLSessions forever. 510af0a7959d838c48e6b4e8dc9ac188ff6bbb6a87Brian Carlstrom */ 520af0a7959d838c48e6b4e8dc9ac188ff6bbb6a87Brian Carlstrom public static final int EXPECTED_DEFAULT_CLIENT_SSL_SESSION_CACHE_SIZE = (IS_RI) ? 0 : 10; 530af0a7959d838c48e6b4e8dc9ac188ff6bbb6a87Brian Carlstrom public static final int EXPECTED_DEFAULT_SERVER_SSL_SESSION_CACHE_SIZE = (IS_RI) ? 0 : 100; 540af0a7959d838c48e6b4e8dc9ac188ff6bbb6a87Brian Carlstrom public static final int EXPECTED_DEFAULT_SSL_SESSION_CACHE_TIMEOUT = (IS_RI) ? 86400 : 0; 55bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom static { 56bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (IS_RI) { 57bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom Security.addProvider(new BouncyCastleProvider()); 58bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 59bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 60bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 61bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom /** 62bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * The Android SSLSocket and SSLServerSocket implementations are 63bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * based on a version of OpenSSL which includes support for RFC 64bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * 4507 session tickets. When using session tickets, the server 65bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * does not need to keep a cache mapping session IDs to SSL 66bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * sessions for reuse. Instead, the client presents the server 67bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * with a session ticket it received from the server earlier, 68bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * which is an SSL session encrypted by the server's secret 69bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * key. Since in this case the server does not need to keep a 70bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * cache, some tests may find different results depending on 71bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * whether or not the session tickets are in use. These tests can 72bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * use this function to determine if loopback SSL connections are 73bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * expected to use session tickets and conditionalize their 74bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * results appropriately. 75bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 76bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public static boolean sslServerSocketSupportsSessionTickets () { 77bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return !IS_RI; 78bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 79bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 80bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public final KeyStore keyStore; 81bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public final char[] keyStorePassword; 82bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public final String publicAlias; 83bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public final String privateAlias; 84bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public final SSLContext sslContext; 85bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public final SSLServerSocket serverSocket; 86bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public final InetAddress host; 87bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public final int port; 88bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 89bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private TestSSLContext(KeyStore keyStore, 90bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom char[] keyStorePassword, 91bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String publicAlias, 92bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String privateAlias, 93bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom SSLContext sslContext, 94bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom SSLServerSocket serverSocket, 95bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom InetAddress host, 96bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom int port) { 97bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.keyStore = keyStore; 98bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.keyStorePassword = keyStorePassword; 99bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.publicAlias = publicAlias; 100bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.privateAlias = privateAlias; 101bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.sslContext = sslContext; 102bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.serverSocket = serverSocket; 103bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.host = host; 104bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.port = port; 105bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 106bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 107e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom /** 108e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom * Usual TestSSLContext creation method, creates underlying 109e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom * SSLContext with certificate and key as well as SSLServerSocket 110e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom * listening provided host and port. 111e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom */ 112bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public static TestSSLContext create() { 113bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom try { 114bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom char[] keyStorePassword = null; 115bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String publicAlias = "public"; 116bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String privateAlias = "private"; 117bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return create(createKeyStore(keyStorePassword, publicAlias, privateAlias), 118e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom keyStorePassword, 119bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom publicAlias, 120bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom privateAlias); 121bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (RuntimeException e) { 122bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom throw e; 123bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (Exception e) { 124bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom throw new RuntimeException(e); 125bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 126bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 127bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 128e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom /** 129e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom * TestSSLContext creation method that allows separate creation of key store 130e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom */ 131bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public static TestSSLContext create(KeyStore keyStore, 132bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom char[] keyStorePassword, 133bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String publicAlias, 134bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String privateAlias) { 135bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom try { 136bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom SSLContext sslContext = createSSLContext(keyStore, keyStorePassword); 137bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 138bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom SSLServerSocket serverSocket = (SSLServerSocket) 139bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom sslContext.getServerSocketFactory().createServerSocket(0); 140bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom InetSocketAddress sa = (InetSocketAddress) serverSocket.getLocalSocketAddress(); 141bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom InetAddress host = sa.getAddress(); 142bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom int port = sa.getPort(); 143bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 144bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return new TestSSLContext(keyStore, keyStorePassword, publicAlias, privateAlias, 145bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom sslContext, serverSocket, host, port); 146bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (RuntimeException e) { 147bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom throw e; 148bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (Exception e) { 149bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom throw new RuntimeException(e); 150bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 151bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 152bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 153bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom /** 154e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom * Create a client version of the server TestSSLContext. The 155e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom * client will trust the server's certificate, but not contain any 156e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom * keys of its own. 157e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom */ 158e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom public static TestSSLContext createClient(TestSSLContext server) { 159e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom try { 160e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom String publicAlias = server.publicAlias; 161e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom Certificate cert = server.keyStore.getCertificate(publicAlias); 162e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom 163e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom KeyStore keyStore = KeyStore.getInstance("BKS"); 164e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom keyStore.load(null, null); 165e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom keyStore.setCertificateEntry(publicAlias, cert); 166e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom 167e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom char[] keyStorePassword = server.keyStorePassword; 168e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom String privateAlias = null; 169e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom 170e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom String tmfa = TrustManagerFactory.getDefaultAlgorithm(); 171e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfa); 172e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom tmf.init(keyStore); 173e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom 174e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom SSLContext sslContext = SSLContext.getInstance("TLS"); 175e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom sslContext.init(null, tmf.getTrustManagers(), new SecureRandom()); 176e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom 177e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom return new TestSSLContext(keyStore, keyStorePassword, publicAlias, publicAlias, 178e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom sslContext, null, null, -1); 179e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom } catch (RuntimeException e) { 180e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom throw e; 181e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom } catch (Exception e) { 182e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom throw new RuntimeException(e); 183e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom } 184e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom } 185e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom 186e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom /** 187bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Create a BKS KeyStore containing an RSAPrivateKey with alias 188bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * "private" and a X509Certificate based on the matching 189bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * RSAPublicKey stored under the alias name publicAlias. 190bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * 191bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * The private key will have a certificate chain including the 192bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * certificate stored under the alias name privateAlias. The 193bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * certificate will be signed by the private key. The certificate 194bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Subject and Issuer Common-Name will be the local host's 195bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * canonical hostname. The certificate will be valid for one day 196bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * before and one day after the time of creation. 197bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * 198bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * The KeyStore is optionally password protected by the 199bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * keyStorePassword argument, which can be null if a password is 200bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * not desired. 201bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * 202bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Based on: 203bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * org.bouncycastle.jce.provider.test.SigTest 204bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * org.bouncycastle.jce.provider.test.CertTest 205bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 206bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public static KeyStore createKeyStore(char[] keyStorePassword, 207bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String publicAlias, 208bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String privateAlias) 209bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom throws Exception { 210bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 211e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom RSAPrivateKey privateKey; 212e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom X509Certificate x509c; 213e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom if (publicAlias == null && privateAlias == null) { 214e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // don't want anything apparently 215e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom privateKey = null; 216e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom x509c = null; 217e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom } else { 218e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // 1.) we make the keys 219e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom int keysize = 1024; 220e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); 221e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom kpg.initialize(keysize, new SecureRandom()); 222e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom KeyPair kp = kpg.generateKeyPair(); 223e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom privateKey = (RSAPrivateKey)kp.getPrivate(); 224e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom RSAPublicKey publicKey = (RSAPublicKey)kp.getPublic(); 225e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom 226e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // 2.) use keys to make certficate 227e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom 228e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // note that there doesn't seem to be a standard way to make a 229e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // certificate using java.* or javax.*. The CertificateFactory 230e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // interface assumes you want to read in a stream of bytes a 231e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // factory specific format. So here we use Bouncy Castle's 232e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // X509V3CertificateGenerator and related classes. 233bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 234e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom Hashtable attributes = new Hashtable(); 235e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom attributes.put(X509Principal.CN, InetAddress.getLocalHost().getCanonicalHostName()); 236e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom X509Principal dn = new X509Principal(attributes); 237e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom 238e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom long millisPerDay = 24 * 60 * 60 * 1000; 239e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom long now = System.currentTimeMillis(); 240e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom Date start = new Date(now - millisPerDay); 241e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom Date end = new Date(now + millisPerDay); 242e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom BigInteger serial = BigInteger.valueOf(1); 243e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom 244e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom X509V3CertificateGenerator x509cg = new X509V3CertificateGenerator(); 245e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom x509cg.setSubjectDN(dn); 246e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom x509cg.setIssuerDN(dn); 247e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom x509cg.setNotBefore(start); 248e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom x509cg.setNotAfter(end); 249e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom x509cg.setPublicKey(publicKey); 250e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom x509cg.setSignatureAlgorithm("sha1WithRSAEncryption"); 251e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom x509cg.setSerialNumber(serial); 252e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom x509c = x509cg.generateX509Certificate(privateKey); 253e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom } 254e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom 255e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom X509Certificate[] x509cc; 256e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom if (privateAlias == null) { 257e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // don't need certificate chain 258e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom x509cc = null; 259e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom } else { 260e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom x509cc = new X509Certificate[] { x509c }; 261e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom } 262bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 263bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // 3.) put certificate and private key to make a key store 264bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom KeyStore ks = KeyStore.getInstance("BKS"); 265bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom ks.load(null, null); 266e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom if (privateAlias != null) { 267e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom ks.setKeyEntry(privateAlias, privateKey, keyStorePassword, x509cc); 268e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom } 269e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom if (publicAlias != null) { 270e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom ks.setCertificateEntry(publicAlias, x509c); 271e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom } 272bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return ks; 273bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 274bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 275bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom /** 276bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Create a SSLContext with a KeyManager using the private key and 277bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * certificate chain from the given KeyStore and a TrustManager 278bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * using the certificates authorities from the same KeyStore. 279bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 280bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public static final SSLContext createSSLContext(final KeyStore keyStore, final char[] keyStorePassword) 281bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom throws Exception { 282bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String kmfa = KeyManagerFactory.getDefaultAlgorithm(); 283bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfa); 284bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom kmf.init(keyStore, keyStorePassword); 285bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 286bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String tmfa = TrustManagerFactory.getDefaultAlgorithm(); 287bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfa); 288bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom tmf.init(keyStore); 289bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 290bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom SSLContext context = SSLContext.getInstance("TLS"); 291bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom()); 292bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return context; 293bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 294bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom} 295