diff options
author | Jesse Wilson <jessewilson@google.com> | 2011-01-31 22:46:07 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-01-31 22:46:07 -0800 |
commit | 2d597ba235f886cbfc311fa9e93ee4b0b7aa95c4 (patch) | |
tree | a80a778103273db7887b4d23d3b9b4668cd1a0b4 | |
parent | 705349bd8b0d649b28a587c9ecb18d39012fa4e2 (diff) | |
parent | 101547d4a82ba21031dc7cb62018720dbd493758 (diff) | |
download | libcore-2d597ba235f886cbfc311fa9e93ee4b0b7aa95c4.zip libcore-2d597ba235f886cbfc311fa9e93ee4b0b7aa95c4.tar.gz libcore-2d597ba235f886cbfc311fa9e93ee4b0b7aa95c4.tar.bz2 |
Merge "Refactoring to add a builder for TestKeyStore." into dalvik-dev
6 files changed, 478 insertions, 501 deletions
diff --git a/luni/src/test/java/libcore/javax/crypto/CipherTest.java b/luni/src/test/java/libcore/javax/crypto/CipherTest.java index 186355f..7919b35 100644 --- a/luni/src/test/java/libcore/javax/crypto/CipherTest.java +++ b/luni/src/test/java/libcore/javax/crypto/CipherTest.java @@ -49,9 +49,9 @@ public final class CipherTest extends TestCase { assertCipherInitWithKeyUsage(KeyUsage.keyAgreement | KeyUsage.decipherOnly, false, true, false, true); - // except when wraping a key is specifically allowed or + // except when wrapping a key is specifically allowed or assertCipherInitWithKeyUsage(KeyUsage.keyEncipherment, false, true, true, true); - // except when wraping data encryption is specifically allowed + // except when wrapping data encryption is specifically allowed assertCipherInitWithKeyUsage(KeyUsage.dataEncipherment, true, true, false, true); } @@ -100,16 +100,12 @@ public final class CipherTest extends TestCase { } } - private Certificate certificateWithKeyUsage(int keyUsage) { + private Certificate certificateWithKeyUsage(int keyUsage) throws Exception { // note the rare usage of non-zero keyUsage - return TestKeyStore.create(new String[] { "RSA" }, - null, - null, - "rsa-dsa-ec", - TestKeyStore.localhost(), - keyUsage, - true, - null, - null).getPrivateKey("RSA", "RSA").getCertificate(); + return new TestKeyStore.Builder() + .aliasPrefix("rsa-dsa-ec") + .keyUsage(keyUsage) + .build() + .getPrivateKey("RSA", "RSA").getCertificate(); } } diff --git a/luni/src/test/java/libcore/javax/net/ssl/KeyManagerFactoryTest.java b/luni/src/test/java/libcore/javax/net/ssl/KeyManagerFactoryTest.java index 2ff9567..a6bdc07 100644 --- a/luni/src/test/java/libcore/javax/net/ssl/KeyManagerFactoryTest.java +++ b/luni/src/test/java/libcore/javax/net/ssl/KeyManagerFactoryTest.java @@ -23,9 +23,9 @@ import java.security.KeyStore.PrivateKeyEntry; import java.security.PrivateKey; import java.security.Provider; import java.security.Security; +import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.util.Arrays; -import java.util.HashSet; import java.util.Set; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; @@ -40,16 +40,18 @@ import libcore.java.security.TestKeyStore; public class KeyManagerFactoryTest extends TestCase { // note the rare usage of DSA keys here in addition to RSA - private static final TestKeyStore TEST_KEY_STORE - = TestKeyStore.create(new String[] { "RSA", "DSA", "EC", "EC_RSA" }, - null, - null, - "rsa-dsa-ec", - TestKeyStore.localhost(), - 0, - true, - null, - null); + private static final TestKeyStore TEST_KEY_STORE; + + static { + try { + TEST_KEY_STORE = new TestKeyStore.Builder() + .keyAlgorithms("RSA", "DSA", "EC", "EC_RSA") + .aliasPrefix("rsa-dsa-ec") + .build(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } public void test_KeyManagerFactory_getDefaultAlgorithm() throws Exception { String algorithm = KeyManagerFactory.getDefaultAlgorithm(); @@ -58,7 +60,7 @@ public class KeyManagerFactoryTest extends TestCase { test_KeyManagerFactory(kmf); } - private static class UseslessManagerFactoryParameters implements ManagerFactoryParameters {} + private static class UselessManagerFactoryParameters implements ManagerFactoryParameters {} private static boolean supportsManagerFactoryParameters(String algorithm) { // Only the "New" one supports ManagerFactoryParameters @@ -94,7 +96,7 @@ public class KeyManagerFactoryTest extends TestCase { // init with useless ManagerFactoryParameters try { - kmf.init(new UseslessManagerFactoryParameters()); + kmf.init(new UselessManagerFactoryParameters()); fail(); } catch (InvalidAlgorithmParameterException expected) { } @@ -123,7 +125,8 @@ public class KeyManagerFactoryTest extends TestCase { test_KeyManagerFactory_getKeyManagers(kmf, false); } - private void test_KeyManagerFactory_getKeyManagers(KeyManagerFactory kmf, boolean empty) { + private void test_KeyManagerFactory_getKeyManagers(KeyManagerFactory kmf, boolean empty) + throws Exception { KeyManager[] keyManagers = kmf.getKeyManagers(); assertNotNull(keyManagers); assertTrue(keyManagers.length > 0); @@ -153,7 +156,8 @@ public class KeyManagerFactoryTest extends TestCase { // extra null at end requires no initialization } - private void test_X509KeyManager(X509KeyManager km, boolean empty, String algorithm) { + private void test_X509KeyManager(X509KeyManager km, boolean empty, String algorithm) + throws Exception { String[] keyTypes = keyTypes(algorithm); for (String keyType : keyTypes) { String[] aliases = km.getClientAliases(keyType, null); @@ -196,7 +200,7 @@ public class KeyManagerFactoryTest extends TestCase { } private void test_X509ExtendedKeyManager(X509ExtendedKeyManager km, - boolean empty, String algorithm) { + boolean empty, String algorithm) throws Exception { String[] keyTypes = keyTypes(algorithm); String a = km.chooseEngineClientAlias(keyTypes, null, null); test_X509KeyManager_alias(km, a, null, true, empty); @@ -215,7 +219,7 @@ public class KeyManagerFactoryTest extends TestCase { String alias, String keyType, boolean many, - boolean empty) { + boolean empty) throws Exception { if (empty || (!many && (keyType == null || keyType.isEmpty()))) { assertNull(keyType, alias); assertNull(keyType, km.getCertificateChain(alias)); @@ -251,8 +255,8 @@ public class KeyManagerFactoryTest extends TestCase { PrivateKeyEntry privateKeyEntry = TEST_KEY_STORE.getPrivateKey(keyAlgName, sigAlgName); if (!"EC".equals(keyAlgName)) { assertEquals(keyType, - Arrays.asList(privateKeyEntry.getCertificateChain()), - Arrays.asList(certificateChain)); + Arrays.<Certificate>asList(privateKeyEntry.getCertificateChain()), + Arrays.<Certificate>asList(certificateChain)); assertEquals(keyType, privateKeyEntry.getPrivateKey(), privateKey); } diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java index d7e7c67..16a3359 100644 --- a/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java +++ b/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java @@ -16,8 +16,6 @@ package libcore.javax.net.ssl; -import libcore.java.security.StandardNames; -import libcore.java.security.TestKeyStore; import java.util.Arrays; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; @@ -27,6 +25,8 @@ import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLSession; import junit.framework.TestCase; +import libcore.java.security.StandardNames; +import libcore.java.security.TestKeyStore; public class SSLEngineTest extends TestCase { @@ -69,16 +69,11 @@ public class SSLEngineTest extends TestCase { public void test_SSLEngine_getSupportedCipherSuites_connect() throws Exception { // note the rare usage of non-RSA keys - TestKeyStore testKeyStore - = TestKeyStore.create(new String[] { "RSA", "DSA", "EC", "EC_RSA" }, - null, - null, - "rsa-dsa-ec", - TestKeyStore.localhost(), - 0, - true, - null, - null); + TestKeyStore testKeyStore = new TestKeyStore.Builder() + .keyAlgorithms("RSA", "DSA", "EC", "EC_RSA") + .aliasPrefix("rsa-dsa-ec") + .ca(true) + .build(); test_SSLEngine_getSupportedCipherSuites_connect(testKeyStore, false); if (StandardNames.IS_RI) { test_SSLEngine_getSupportedCipherSuites_connect(testKeyStore, true); diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java index 35346a2..7ca5a63 100644 --- a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java +++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java @@ -55,16 +55,11 @@ public class SSLSocketTest extends TestCase { public void test_SSLSocket_getSupportedCipherSuites_connect() throws Exception { // note the rare usage of non-RSA keys - TestKeyStore testKeyStore - = TestKeyStore.create(new String[] { "RSA", "DSA", "EC", "EC_RSA" }, - null, - null, - "rsa-dsa-ec", - TestKeyStore.localhost(), - 0, - true, - null, - null); + TestKeyStore testKeyStore = new TestKeyStore.Builder() + .keyAlgorithms("RSA", "DSA", "EC", "EC_RSA") + .aliasPrefix("rsa-dsa-ec") + .ca(true) + .build(); if (StandardNames.IS_RI) { test_SSLSocket_getSupportedCipherSuites_connect(testKeyStore, StandardNames.JSSE_PROVIDER_NAME, @@ -382,9 +377,12 @@ public class SSLSocketTest extends TestCase { if (false) { System.out.println("Session=" + session); System.out.println("CipherSuite=" + cipherSuite); - System.out.println("LocalCertificates=" + localCertificates); - System.out.println("PeerCertificates=" + peerCertificates); - System.out.println("PeerCertificateChain=" + peerCertificateChain); + System.out.println("LocalCertificates=" + + Arrays.toString(localCertificates)); + System.out.println("PeerCertificates=" + + Arrays.toString(peerCertificates)); + System.out.println("PeerCertificateChain=" + + Arrays.toString(peerCertificateChain)); System.out.println("PeerPrincipal=" + peerPrincipal); System.out.println("LocalPrincipal=" + localPrincipal); System.out.println("Socket=" + socket); @@ -1058,7 +1056,7 @@ public class SSLSocketTest extends TestCase { /** * Not run by default by JUnit, but can be run by Vogar by - * specifying it explictly (or with main method below) + * specifying it explicitly (or with main method below) */ public void stress_test_TestSSLSocketPair_create() { final boolean verbose = true; @@ -1081,7 +1079,7 @@ public class SSLSocketTest extends TestCase { } } - public static final void main (String[] args) { + public static void main (String[] args) { new SSLSocketTest().stress_test_TestSSLSocketPair_create(); } } diff --git a/luni/src/test/java/libcore/javax/net/ssl/TrustManagerFactoryTest.java b/luni/src/test/java/libcore/javax/net/ssl/TrustManagerFactoryTest.java index e92bf67..b82b4d2 100644 --- a/luni/src/test/java/libcore/javax/net/ssl/TrustManagerFactoryTest.java +++ b/luni/src/test/java/libcore/javax/net/ssl/TrustManagerFactoryTest.java @@ -17,11 +17,10 @@ package libcore.javax.net.ssl; import java.security.InvalidAlgorithmParameterException; -import java.security.KeyStore.PrivateKeyEntry; import java.security.KeyStore; +import java.security.KeyStore.PrivateKeyEntry; import java.security.Provider; import java.security.Security; -import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.PKIXBuilderParameters; import java.security.cert.PKIXParameters; @@ -41,16 +40,18 @@ public class TrustManagerFactoryTest extends TestCase { private static final String [] KEY_TYPES = new String[] { "RSA", "DSA", "EC", "EC_RSA" }; // note the rare usage of DSA keys here in addition to RSA - private static final TestKeyStore TEST_KEY_STORE - = TestKeyStore.create(KEY_TYPES, - null, - null, - "rsa-dsa-ec", - TestKeyStore.localhost(), - 0, - true, - null, - null); + private static final TestKeyStore TEST_KEY_STORE; + static { + try { + TEST_KEY_STORE = new TestKeyStore.Builder() + .keyAlgorithms(KEY_TYPES) + .aliasPrefix("rsa-dsa-ec") + .ca(true) + .build(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } public void test_TrustManagerFactory_getDefaultAlgorithm() throws Exception { String algorithm = TrustManagerFactory.getDefaultAlgorithm(); @@ -59,7 +60,7 @@ public class TrustManagerFactoryTest extends TestCase { test_TrustManagerFactory(tmf, StandardNames.IS_RI); } - private static class UseslessManagerFactoryParameters implements ManagerFactoryParameters {} + private static class UselessManagerFactoryParameters implements ManagerFactoryParameters {} private void test_TrustManagerFactory(TrustManagerFactory tmf, boolean supportsManagerFactoryParameters) @@ -84,7 +85,7 @@ public class TrustManagerFactoryTest extends TestCase { // init with useless ManagerFactoryParameters try { - tmf.init(new UseslessManagerFactoryParameters()); + tmf.init(new UselessManagerFactoryParameters()); fail(); } catch (InvalidAlgorithmParameterException expected) { } @@ -141,7 +142,7 @@ public class TrustManagerFactoryTest extends TestCase { assertNotNull(issuers); assertTrue(issuers.length > 1); assertNotSame(issuers, tm.getAcceptedIssuers()); - boolean defaultTrustmanager + boolean defaultTrustManager // RI de-duplicates certs from TrustedCertificateEntry and PrivateKeyEntry = issuers.length > (StandardNames.IS_RI ? 1 : 2) * KEY_TYPES.length; @@ -149,7 +150,7 @@ public class TrustManagerFactoryTest extends TestCase { String sigAlgName = TestKeyStore.signatureAlgorithm(keyType); PrivateKeyEntry pke = TEST_KEY_STORE.getPrivateKey(keyAlgName, sigAlgName); X509Certificate[] chain = (X509Certificate[]) pke.getCertificateChain(); - if (defaultTrustmanager) { + if (defaultTrustManager) { try { tm.checkClientTrusted(chain, keyType); fail(); diff --git a/support/src/test/java/libcore/java/security/TestKeyStore.java b/support/src/test/java/libcore/java/security/TestKeyStore.java index 94daaf5..7c8b0bc 100644 --- a/support/src/test/java/libcore/java/security/TestKeyStore.java +++ b/support/src/test/java/libcore/java/security/TestKeyStore.java @@ -27,14 +27,16 @@ import java.io.ByteArrayInputStream; import java.io.PrintStream; import java.math.BigInteger; import java.net.InetAddress; -import java.security.Key; +import java.net.UnknownHostException; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; +import java.security.KeyStore; import java.security.KeyStore.PasswordProtection; import java.security.KeyStore.PrivateKeyEntry; import java.security.KeyStore.TrustedCertificateEntry; -import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; import java.security.Principal; import java.security.PrivateKey; import java.security.PublicKey; @@ -66,6 +68,14 @@ import libcore.javax.net.ssl.TestTrustManager; */ public final class TestKeyStore extends Assert { + private static final TestKeyStore ROOT_CA; + private static final TestKeyStore INTERMEDIATE_CA; + private static final TestKeyStore SERVER; + private static final TestKeyStore CLIENT; + private static final TestKeyStore CLIENT_CERTIFICATE; + private static final TestKeyStore ROOT_CA_2; + private static final TestKeyStore CLIENT_2; + static { if (StandardNames.IS_RI) { // Needed to create BKS keystore but add at end so most @@ -73,7 +83,43 @@ public final class TestKeyStore extends Assert { Security.insertProviderAt(new BouncyCastleProvider(), Security.getProviders().length+1); } + + try { + ROOT_CA = new Builder() + .aliasPrefix("RootCA") + .subject("Test Root Certificate Authority") + .ca(true) + .build(); + INTERMEDIATE_CA = new Builder() + .aliasPrefix("IntermediateCA") + .subject("Test Intermediate Certificate Authority") + .ca(true) + .signer(ROOT_CA.getPrivateKey("RSA", "RSA")) + .rootCa(ROOT_CA.getRootCertificate("RSA")) + .build(); + SERVER = new Builder() + .aliasPrefix("server") + .signer(INTERMEDIATE_CA.getPrivateKey("RSA", "RSA")) + .rootCa(INTERMEDIATE_CA.getRootCertificate("RSA")) + .build(); + CLIENT = new TestKeyStore(createClient(INTERMEDIATE_CA.keyStore), null, null); + CLIENT_CERTIFICATE = new Builder() + .aliasPrefix("client") + .subject("test@user") + .signer(INTERMEDIATE_CA.getPrivateKey("RSA", "RSA")) + .rootCa(INTERMEDIATE_CA.getRootCertificate("RSA")) + .build(); + ROOT_CA_2 = new Builder() + .aliasPrefix("RootCA2") + .subject("Test Root Certificate Authority 2") + .ca(true) + .build(); + CLIENT_2 = new TestKeyStore(createClient(ROOT_CA_2.keyStore), null, null); + } catch (Exception e) { + throw new RuntimeException(e); + } } + private static final boolean TEST_MANAGERS = true; public final KeyStore keyStore; @@ -84,9 +130,8 @@ public final class TestKeyStore extends Assert { public final TestKeyManager keyManager; public final TestTrustManager trustManager; - private TestKeyStore(KeyStore keyStore, - char[] storePassword, - char[] keyPassword) { + private TestKeyStore(KeyStore keyStore, char[] storePassword, char[] keyPassword) + throws Exception { this.keyStore = keyStore; this.storePassword = storePassword; this.keyPassword = keyPassword; @@ -96,85 +141,21 @@ public final class TestKeyStore extends Assert { this.trustManager = (TestTrustManager)trustManagers[0]; } - public static KeyManager[] createKeyManagers(final KeyStore keyStore, - final char[] storePassword) { - try { - String kmfa = KeyManagerFactory.getDefaultAlgorithm(); - KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfa); - kmf.init(keyStore, storePassword); - return TestKeyManager.wrap(kmf.getKeyManagers()); - } catch (Exception e) { - throw new RuntimeException(e); - } + public static KeyManager[] createKeyManagers(KeyStore keyStore, char[] storePassword) + throws Exception { + String kmfa = KeyManagerFactory.getDefaultAlgorithm(); + KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfa); + kmf.init(keyStore, storePassword); + return TestKeyManager.wrap(kmf.getKeyManagers()); } - public static TrustManager[] createTrustManagers(final KeyStore keyStore) { - try { - String tmfa = TrustManagerFactory.getDefaultAlgorithm(); - TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfa); - tmf.init(keyStore); - return TestTrustManager.wrap(tmf.getTrustManagers()); - } catch (Exception e) { - throw new RuntimeException(e); - } + public static TrustManager[] createTrustManagers(final KeyStore keyStore) throws Exception { + String tmfa = TrustManagerFactory.getDefaultAlgorithm(); + TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfa); + tmf.init(keyStore); + return TestTrustManager.wrap(tmf.getTrustManagers()); } - private static final TestKeyStore ROOT_CA - = create(new String[] { "RSA" }, - null, - null, - "RootCA", - x509Principal("Test Root Certificate Authority"), - 0, - true, - null, - null); - private static final TestKeyStore INTERMEDIATE_CA - = create(new String[] { "RSA" }, - null, - null, - "IntermediateCA", - x509Principal("Test Intermediate Certificate Authority"), - 0, - true, - ROOT_CA.getPrivateKey("RSA", "RSA"), - ROOT_CA.getRootCertificate("RSA")); - private static final TestKeyStore SERVER - = create(new String[] { "RSA" }, - null, - null, - "server", - localhost(), - 0, - false, - INTERMEDIATE_CA.getPrivateKey("RSA", "RSA"), - INTERMEDIATE_CA.getRootCertificate("RSA")); - private static final TestKeyStore CLIENT - = new TestKeyStore(createClient(INTERMEDIATE_CA.keyStore), null, null); - private static final TestKeyStore CLIENT_CERTIFICATE - = create(new String[] { "RSA" }, - null, - null, - "client", - x509Principal("test@user"), - 0, - false, - INTERMEDIATE_CA.getPrivateKey("RSA", "RSA"), - INTERMEDIATE_CA.getRootCertificate("RSA")); - - private static final TestKeyStore ROOT_CA_2 - = create(new String[] { "RSA" }, - null, - null, - "RootCA2", - x509Principal("Test Root Certificate Authority 2"), - 0, - true, - null, - null); - private static final TestKeyStore CLIENT_2 - = new TestKeyStore(createClient(ROOT_CA_2.keyStore), null, null); - /** * Return a server keystore with a matched RSA certificate and * private key as well as a CA certificate. @@ -208,28 +189,78 @@ public final class TestKeyStore extends Assert { } /** - * Create a new KeyStore containing the requested key types. - * Since key generation can be expensive, most tests should reuse - * the RSA-only singleton instance returned by TestKeyStore.get - * - * @param keyAlgorithms The requested key types to generate and include - * @param keyStorePassword Password used to protect the private key - * @param aliasPrefix A unique prefix to identify the key aliases - * @param keyUsage {@link KeyUsage} bit mask for 2.5.29.15 extension - * @param ca true If the keys being created are for a CA - * @param signer If non-null, a private key entry to be used for signing, otherwise self-sign - * @param signer If non-null, a root CA to include in the final store + * Creates KeyStores containing the requested key types. Since key + * generation can be expensive, most tests should reuse the RSA-only + * singleton instance returned by TestKeyStore.get. */ - public static TestKeyStore create(String[] keyAlgorithms, - char[] storePassword, - char[] keyPassword, - String aliasPrefix, - X509Principal subject, - int keyUsage, - boolean ca, - PrivateKeyEntry signer, - Certificate rootCa) { - try { + public static class Builder { + private String[] keyAlgorithms = { "RSA" }; + private char[] storePassword; + private char[] keyPassword; + private String aliasPrefix; + private X509Principal subject; + private int keyUsage; + private boolean ca; + private PrivateKeyEntry signer; + private Certificate rootCa; + + public Builder() throws Exception { + subject = localhost(); + } + + /** + * Sets the requested key types to generate and include. The default is + * RSA only. + */ + public Builder keyAlgorithms(String... keyAlgorithms) { + this.keyAlgorithms = keyAlgorithms; + return this; + } + + /** A unique prefix to identify the key aliases */ + public Builder aliasPrefix(String aliasPrefix) { + this.aliasPrefix = aliasPrefix; + return this; + } + + /** + * Sets the subject common name. The default is the local host's + * canonical name. + */ + public Builder subject(X509Principal subject) { + this.subject = subject; + return this; + } + + public Builder subject(String commonName) { + return subject(x509Principal(commonName)); + } + + /** {@link KeyUsage} bit mask for 2.5.29.15 extension */ + public Builder keyUsage(int keyUsage) { + this.keyUsage = keyUsage; + return this; + } + + /** true If the keys being created are for a CA */ + public Builder ca(boolean ca) { + this.ca = ca; + return this; + } + + /** a private key entry to be used for signing, otherwise self-sign */ + public Builder signer(PrivateKeyEntry signer) { + this.signer = signer; + return this; + } + + /** a root CA to include in the final store */ + public Builder rootCa(Certificate rootCa) { + this.rootCa = rootCa; + return this; + } + + public TestKeyStore build() throws Exception { if (StandardNames.IS_RI) { // JKS does not allow null password if (storePassword == null) { @@ -239,28 +270,17 @@ public final class TestKeyStore extends Assert { keyPassword = "password".toCharArray(); } } + KeyStore keyStore = createKeyStore(); - boolean ecRsa = false; for (String keyAlgorithm : keyAlgorithms) { String publicAlias = aliasPrefix + "-public-" + keyAlgorithm; String privateAlias = aliasPrefix + "-private-" + keyAlgorithm; if (keyAlgorithm.equals("EC_RSA") && signer == null && rootCa == null) { - createKeys(keyStore, keyPassword, - keyAlgorithm, - publicAlias, privateAlias, - subject, - keyUsage, - ca, - privateKey(keyStore, keyPassword, "RSA", "RSA")); + createKeys(keyStore, keyAlgorithm, publicAlias, privateAlias, + privateKey(keyStore, keyPassword, "RSA", "RSA")); continue; } - createKeys(keyStore, keyPassword, - keyAlgorithm, - publicAlias, privateAlias, - subject, - keyUsage, - ca, - signer); + createKeys(keyStore, keyAlgorithm, publicAlias, privateAlias, signer); } if (rootCa != null) { keyStore.setCertificateEntry(aliasPrefix @@ -269,10 +289,171 @@ public final class TestKeyStore extends Assert { rootCa); } return new TestKeyStore(keyStore, storePassword, keyPassword); - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e); + } + + /** + * Add newly generated keys of a given key type to an existing + * KeyStore. The PrivateKey will be stored under the specified + * private alias name. The X509Certificate will be stored on the + * public alias name and have the given subject distinguished + * name. + * + * If a CA is provided, it will be used to sign the generated + * certificate. Otherwise, the certificate will be self + * signed. The certificate will be valid for one day before and + * one day after the time of creation. + * + * Based on: + * org.bouncycastle.jce.provider.test.SigTest + * org.bouncycastle.jce.provider.test.CertTest + */ + private KeyStore createKeys(KeyStore keyStore, + String keyAlgorithm, + String publicAlias, + String privateAlias, + PrivateKeyEntry signer) throws Exception { + PrivateKey caKey; + X509Certificate caCert; + X509Certificate[] caCertChain; + if (signer == null) { + caKey = null; + caCert = null; + caCertChain = null; + } else { + caKey = signer.getPrivateKey(); + caCert = (X509Certificate)signer.getCertificate(); + caCertChain = (X509Certificate[])signer.getCertificateChain(); + } + + PrivateKey privateKey; + X509Certificate x509c; + if (publicAlias == null && privateAlias == null) { + // don't want anything apparently + privateKey = null; + x509c = null; + } else { + // 1.) we make the keys + int keySize; + String signatureAlgorithm; + if (keyAlgorithm.equals("RSA")) { + keySize = StandardNames.IS_RI ? 1024 : 512; // 512 breaks SSL_RSA_EXPORT_* on RI + signatureAlgorithm = "sha1WithRSA"; + } else if (keyAlgorithm.equals("DSA")) { + keySize = 512; + signatureAlgorithm = "sha1WithDSA"; + } else if (keyAlgorithm.equals("EC")) { + keySize = 256; + signatureAlgorithm = "sha1WithECDSA"; + } else if (keyAlgorithm.equals("EC_RSA")) { + keySize = 256; + keyAlgorithm = "EC"; + signatureAlgorithm = "sha1WithRSA"; + } else { + throw new IllegalArgumentException("Unknown key algorithm " + keyAlgorithm); + } + + KeyPairGenerator kpg = KeyPairGenerator.getInstance(keyAlgorithm); + kpg.initialize(keySize, new SecureRandom()); + + KeyPair kp = kpg.generateKeyPair(); + privateKey = kp.getPrivate(); + PublicKey publicKey = kp.getPublic(); + // 2.) use keys to make certificate + + // note that there doesn't seem to be a standard way to make a + // certificate using java.* or javax.*. The CertificateFactory + // interface assumes you want to read in a stream of bytes a + // factory specific format. So here we use Bouncy Castle's + // X509V3CertificateGenerator and related classes. + X509Principal issuer; + if (caCert == null) { + issuer = subject; + } else { + Principal xp = caCert.getSubjectDN(); + issuer = new X509Principal(new X509Name(xp.getName())); + } + + long millisPerDay = 24 * 60 * 60 * 1000; + long now = System.currentTimeMillis(); + Date start = new Date(now - millisPerDay); + Date end = new Date(now + millisPerDay); + BigInteger serial = BigInteger.valueOf(1); + + X509V3CertificateGenerator x509cg = new X509V3CertificateGenerator(); + x509cg.setSubjectDN(subject); + x509cg.setIssuerDN(issuer); + x509cg.setNotBefore(start); + x509cg.setNotAfter(end); + x509cg.setPublicKey(publicKey); + x509cg.setSignatureAlgorithm(signatureAlgorithm); + x509cg.setSerialNumber(serial); + if (keyUsage != 0) { + x509cg.addExtension(X509Extensions.KeyUsage, + true, + new KeyUsage(keyUsage)); + } + if (ca) { + x509cg.addExtension(X509Extensions.BasicConstraints, + true, + new BasicConstraints(true)); + } + PrivateKey signingKey = (caKey == null) ? privateKey : caKey; + if (signingKey instanceof ECPrivateKey) { + /* + * bouncycastle needs its own ECPrivateKey implementation + */ + KeyFactory kf = KeyFactory.getInstance(keyAlgorithm, "BC"); + PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(signingKey.getEncoded()); + signingKey = kf.generatePrivate(ks); + } + x509c = x509cg.generateX509Certificate(signingKey); + if (StandardNames.IS_RI) { + /* + * The RI can't handle the BC EC signature algorithm + * string of "ECDSA", since it expects "...WITHEC...", + * so convert from BC to RI X509Certificate + * implementation via bytes. + */ + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + ByteArrayInputStream bais = new ByteArrayInputStream(x509c.getEncoded()); + Certificate c = cf.generateCertificate(bais); + x509c = (X509Certificate) c; + } + } + + X509Certificate[] x509cc; + if (privateAlias == null) { + // don't need certificate chain + x509cc = null; + } else if (caCertChain == null) { + x509cc = new X509Certificate[] { x509c }; + } else { + x509cc = new X509Certificate[caCertChain.length+1]; + x509cc[0] = x509c; + System.arraycopy(caCertChain, 0, x509cc, 1, caCertChain.length); + } + + // 3.) put certificate and private key into the key store + if (privateAlias != null) { + keyStore.setKeyEntry(privateAlias, privateKey, keyPassword, x509cc); + } + if (publicAlias != null) { + keyStore.setCertificateEntry(publicAlias, x509c); + } + return keyStore; + } + + private X509Principal localhost() throws UnknownHostException { + return x509Principal(InetAddress.getLocalHost().getCanonicalHostName()); + } + + /** + * Create an X509Principal with the given attributes + */ + public static X509Principal x509Principal(String commonName) { + Hashtable attributes = new Hashtable(); + attributes.put(X509Principal.CN, commonName); + return new X509Principal(attributes); } } @@ -320,187 +501,12 @@ public final class TestKeyStore extends Assert { } /** - * Add newly generated keys of a given key type to an existing - * KeyStore. The PrivateKey will be stored under the specified - * private alias name. The X509Certificate will be stored on the - * public alias name and have the given subject distiguished - * name. - * - * If a CA is provided, it will be used to sign the generated - * certificate. Otherwise, the certificate will be self - * signed. The certificate will be valid for one day before and - * one day after the time of creation. - * - * Based on: - * org.bouncycastle.jce.provider.test.SigTest - * org.bouncycastle.jce.provider.test.CertTest - */ - public static KeyStore createKeys(KeyStore keyStore, - char[] keyPassword, - String keyAlgorithm, - String publicAlias, - String privateAlias, - X509Principal subject, - int keyUsage, - boolean ca, - PrivateKeyEntry signer) throws Exception { - PrivateKey caKey; - X509Certificate caCert; - X509Certificate[] caCertChain; - if (signer == null) { - caKey = null; - caCert = null; - caCertChain = null; - } else { - caKey = signer.getPrivateKey(); - caCert = (X509Certificate)signer.getCertificate(); - caCertChain = (X509Certificate[])signer.getCertificateChain(); - } - - PrivateKey privateKey; - X509Certificate x509c; - if (publicAlias == null && privateAlias == null) { - // don't want anything apparently - privateKey = null; - x509c = null; - } else { - // 1.) we make the keys - int keySize; - String signatureAlgorithm; - if (keyAlgorithm.equals("RSA")) { - keySize = StandardNames.IS_RI ? 1024 : 512; // 512 breaks SSL_RSA_EXPORT_* on RI - signatureAlgorithm = "sha1WithRSA"; - } else if (keyAlgorithm.equals("DSA")) { - keySize = 512; - signatureAlgorithm = "sha1WithDSA"; - } else if (keyAlgorithm.equals("EC")) { - keySize = 256; - signatureAlgorithm = "sha1WithECDSA"; - } else if (keyAlgorithm.equals("EC_RSA")) { - keySize = 256; - keyAlgorithm = "EC"; - signatureAlgorithm = "sha1WithRSA"; - } else { - throw new IllegalArgumentException("Unknown key algorithm " + keyAlgorithm); - } - - KeyPairGenerator kpg = KeyPairGenerator.getInstance(keyAlgorithm); - kpg.initialize(keySize, new SecureRandom()); - - KeyPair kp = kpg.generateKeyPair(); - privateKey = (PrivateKey)kp.getPrivate(); - PublicKey publicKey = (PublicKey)kp.getPublic(); - // 2.) use keys to make certficate - - // note that there doesn't seem to be a standard way to make a - // certificate using java.* or javax.*. The CertificateFactory - // interface assumes you want to read in a stream of bytes a - // factory specific format. So here we use Bouncy Castle's - // X509V3CertificateGenerator and related classes. - X509Principal issuer; - if (caCert == null) { - issuer = subject; - } else { - Principal xp = caCert.getSubjectDN(); - issuer = new X509Principal(new X509Name(xp.getName())); - } - - long millisPerDay = 24 * 60 * 60 * 1000; - long now = System.currentTimeMillis(); - Date start = new Date(now - millisPerDay); - Date end = new Date(now + millisPerDay); - BigInteger serial = BigInteger.valueOf(1); - - X509V3CertificateGenerator x509cg = new X509V3CertificateGenerator(); - x509cg.setSubjectDN(subject); - x509cg.setIssuerDN(issuer); - x509cg.setNotBefore(start); - x509cg.setNotAfter(end); - x509cg.setPublicKey(publicKey); - x509cg.setSignatureAlgorithm(signatureAlgorithm); - x509cg.setSerialNumber(serial); - if (keyUsage != 0) { - x509cg.addExtension(X509Extensions.KeyUsage, - true, - new KeyUsage(keyUsage)); - } - if (ca) { - x509cg.addExtension(X509Extensions.BasicConstraints, - true, - new BasicConstraints(true)); - } - PrivateKey signingKey = (caKey == null) ? privateKey : caKey; - if (signingKey instanceof ECPrivateKey) { - /* - * bouncycastle needs its own ECPrivateKey implementation - */ - KeyFactory kf = KeyFactory.getInstance(keyAlgorithm, "BC"); - PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(signingKey.getEncoded()); - signingKey = (PrivateKey) kf.generatePrivate(ks); - } - x509c = x509cg.generateX509Certificate(signingKey); - if (StandardNames.IS_RI) { - /* - * The RI can't handle the BC EC signature algorithm - * string of "ECDSA", since it expects "...WITHEC...", - * so convert from BC to RI X509Certificate - * implementation via bytes. - */ - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - ByteArrayInputStream bais = new ByteArrayInputStream(x509c.getEncoded()); - Certificate c = cf.generateCertificate(bais); - x509c = (X509Certificate) c; - } - } - - X509Certificate[] x509cc; - if (privateAlias == null) { - // don't need certificate chain - x509cc = null; - } else if (caCertChain == null) { - x509cc = new X509Certificate[] { x509c }; - } else { - x509cc = new X509Certificate[caCertChain.length+1]; - x509cc[0] = x509c; - System.arraycopy(caCertChain, 0, x509cc, 1, caCertChain.length); - } - - // 3.) put certificate and private key into the key store - if (privateAlias != null) { - keyStore.setKeyEntry(privateAlias, privateKey, keyPassword, x509cc); - } - if (publicAlias != null) { - keyStore.setCertificateEntry(publicAlias, x509c); - } - return keyStore; - } - - /** - * Create an X509Principal with the given attributes - */ - public static X509Principal localhost() { - try { - return x509Principal(InetAddress.getLocalHost().getCanonicalHostName()); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * Create an X509Principal with the given attributes - */ - public static X509Principal x509Principal(String commonName) { - Hashtable attributes = new Hashtable(); - attributes.put(X509Principal.CN, commonName); - return new X509Principal(attributes); - } - - /** * Return the only private key in a TestKeyStore for the given * algorithms. Throws IllegalStateException if there are are more * or less than one. */ - public PrivateKeyEntry getPrivateKey(String keyAlgorithm, String signatureAlgorithm) { + public PrivateKeyEntry getPrivateKey(String keyAlgorithm, String signatureAlgorithm) + throws Exception { return privateKey(keyStore, keyPassword, keyAlgorithm, signatureAlgorithm); } @@ -509,43 +515,37 @@ public final class TestKeyStore extends Assert { * algorithms. Throws IllegalStateException if there are are more * or less than one. */ - public static PrivateKeyEntry privateKey(KeyStore keyStore, - char[] keyPassword, - String keyAlgorithm, - String signatureAlgorithm) { - try { - PrivateKeyEntry found = null; - PasswordProtection password = new PasswordProtection(keyPassword); - for (String alias: Collections.list(keyStore.aliases())) { - if (!keyStore.entryInstanceOf(alias, PrivateKeyEntry.class)) { - continue; - } - PrivateKeyEntry privateKey = (PrivateKeyEntry) keyStore.getEntry(alias, password); - if (!privateKey.getPrivateKey().getAlgorithm().equals(keyAlgorithm)) { - continue; - } - X509Certificate certificate = (X509Certificate) privateKey.getCertificate(); - if (!certificate.getSigAlgName().contains(signatureAlgorithm)) { - continue; - } - if (found != null) { - throw new IllegalStateException("keyStore has more than one private key for " - + " keyAlgorithm: " + keyAlgorithm - + " signatureAlgorithm: " + signatureAlgorithm - + "\nfirst: " + found.getPrivateKey() - + "\nsecond: " + privateKey.getPrivateKey() ); - } - found = privateKey; + public static PrivateKeyEntry privateKey(KeyStore keyStore, char[] keyPassword, + String keyAlgorithm, String signatureAlgorithm) throws Exception { + PrivateKeyEntry found = null; + PasswordProtection password = new PasswordProtection(keyPassword); + for (String alias: Collections.list(keyStore.aliases())) { + if (!keyStore.entryInstanceOf(alias, PrivateKeyEntry.class)) { + continue; + } + PrivateKeyEntry privateKey = (PrivateKeyEntry) keyStore.getEntry(alias, password); + if (!privateKey.getPrivateKey().getAlgorithm().equals(keyAlgorithm)) { + continue; + } + X509Certificate certificate = (X509Certificate) privateKey.getCertificate(); + if (!certificate.getSigAlgName().contains(signatureAlgorithm)) { + continue; } - if (found == null) { - throw new IllegalStateException("keyStore contained no private key for " + if (found != null) { + throw new IllegalStateException("keyStore has more than one private key for " + " keyAlgorithm: " + keyAlgorithm - + " signatureAlgorithm: " + signatureAlgorithm); + + " signatureAlgorithm: " + signatureAlgorithm + + "\nfirst: " + found.getPrivateKey() + + "\nsecond: " + privateKey.getPrivateKey() ); } - return found; - } catch (Exception e) { - throw new RuntimeException(e); + found = privateKey; + } + if (found == null) { + throw new IllegalStateException("keyStore contained no private key for " + + " keyAlgorithm: " + keyAlgorithm + + " signatureAlgorithm: " + signatureAlgorithm); } + return found; } /** @@ -553,7 +553,7 @@ public final class TestKeyStore extends Assert { * for the given algorithm. Throws IllegalStateException if there * are are more or less than one. */ - public Certificate getRootCertificate(String algorithm) { + public Certificate getRootCertificate(String algorithm) throws Exception { return rootCertificate(keyStore, algorithm); } @@ -562,61 +562,51 @@ public final class TestKeyStore extends Assert { * the given algorithm. Throws IllegalStateException if there are * are more or less than one. */ - public static Certificate rootCertificate(KeyStore keyStore, - String algorithm) { - try { - Certificate found = null; - for (String alias: Collections.list(keyStore.aliases())) { - if (!keyStore.entryInstanceOf(alias, TrustedCertificateEntry.class)) { - continue; - } - TrustedCertificateEntry certificateEntry = - (TrustedCertificateEntry) keyStore.getEntry(alias, null); - Certificate certificate = certificateEntry.getTrustedCertificate(); - if (!certificate.getPublicKey().getAlgorithm().equals(algorithm)) { - continue; - } - if (!(certificate instanceof X509Certificate)) { - continue; - } - X509Certificate x = (X509Certificate) certificate; - if (!x.getIssuerDN().equals(x.getSubjectDN())) { - continue; - } - if (found != null) { - throw new IllegalStateException("keyStore has more than one root CA for " - + algorithm - + "\nfirst: " + found - + "\nsecond: " + certificate ); - } - found = certificate; + public static Certificate rootCertificate(KeyStore keyStore, String algorithm) + throws Exception { + Certificate found = null; + for (String alias: Collections.list(keyStore.aliases())) { + if (!keyStore.entryInstanceOf(alias, TrustedCertificateEntry.class)) { + continue; + } + TrustedCertificateEntry certificateEntry = + (TrustedCertificateEntry) keyStore.getEntry(alias, null); + Certificate certificate = certificateEntry.getTrustedCertificate(); + if (!certificate.getPublicKey().getAlgorithm().equals(algorithm)) { + continue; } - if (found == null) { - throw new IllegalStateException("keyStore contained no root CA for " + algorithm); + if (!(certificate instanceof X509Certificate)) { + continue; } - return found; - } catch (Exception e) { - throw new RuntimeException(e); + X509Certificate x = (X509Certificate) certificate; + if (!x.getIssuerDN().equals(x.getSubjectDN())) { + continue; + } + if (found != null) { + throw new IllegalStateException("keyStore has more than one root CA for " + + algorithm + + "\nfirst: " + found + + "\nsecond: " + certificate ); + } + found = certificate; + } + if (found == null) { + throw new IllegalStateException("keyStore contained no root CA for " + algorithm); } + return found; } /** * Create a client key store that only contains self-signed certificates but no private keys */ - public static KeyStore createClient(KeyStore caKeyStore) { - try { - KeyStore clientKeyStore = createKeyStore(); - copySelfSignedCertificates(clientKeyStore, caKeyStore); - return clientKeyStore; - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e); - } + public static KeyStore createClient(KeyStore caKeyStore) throws Exception { + KeyStore clientKeyStore = createKeyStore(); + copySelfSignedCertificates(clientKeyStore, caKeyStore); + return clientKeyStore; } /** - * Copy self-signed certifcates from one key store to another. + * Copy self-signed certificates from one key store to another. * Returns true if successful, false if no match found. */ public static boolean copySelfSignedCertificates(KeyStore dst, KeyStore src) throws Exception { @@ -636,7 +626,7 @@ public final class TestKeyStore extends Assert { } /** - * Copy named certifcates from one key store to another. + * Copy named certificates from one key store to another. * Returns true if successful, false if no match found. */ public static boolean copyCertificate(Principal subject, KeyStore dst, KeyStore src) @@ -658,64 +648,57 @@ public final class TestKeyStore extends Assert { /** * Dump a key store for debugging. */ - public static void dump(String context, - KeyStore keyStore, - char[] keyPassword) { - try { - PrintStream out = System.out; - out.println("context=" + context); - out.println("\tkeyStore=" + keyStore); - out.println("\tkeyStore.type=" + keyStore.getType()); - out.println("\tkeyStore.provider=" + keyStore.getProvider()); - out.println("\tkeyPassword=" - + ((keyPassword == null) ? null : new String(keyPassword))); - out.println("\tsize=" + keyStore.size()); - for (String alias: Collections.list(keyStore.aliases())) { - out.println("alias=" + alias); - out.println("\tcreationDate=" + keyStore.getCreationDate(alias)); - if (keyStore.isCertificateEntry(alias)) { - out.println("\tcertificate:"); - out.println("=========================================="); - out.println(keyStore.getCertificate(alias)); - out.println("=========================================="); - continue; - } - if (keyStore.isKeyEntry(alias)) { - out.println("\tkey:"); - out.println("=========================================="); - String key; + public static void dump(String context, KeyStore keyStore, char[] keyPassword) + throws KeyStoreException, NoSuchAlgorithmException { + PrintStream out = System.out; + out.println("context=" + context); + out.println("\tkeyStore=" + keyStore); + out.println("\tkeyStore.type=" + keyStore.getType()); + out.println("\tkeyStore.provider=" + keyStore.getProvider()); + out.println("\tkeyPassword=" + + ((keyPassword == null) ? null : new String(keyPassword))); + out.println("\tsize=" + keyStore.size()); + for (String alias: Collections.list(keyStore.aliases())) { + out.println("alias=" + alias); + out.println("\tcreationDate=" + keyStore.getCreationDate(alias)); + if (keyStore.isCertificateEntry(alias)) { + out.println("\tcertificate:"); + out.println("=========================================="); + out.println(keyStore.getCertificate(alias)); + out.println("=========================================="); + continue; + } + if (keyStore.isKeyEntry(alias)) { + out.println("\tkey:"); + out.println("=========================================="); + String key; + try { + key = ("Key retrieved using password\n" + + keyStore.getKey(alias, keyPassword)); + } catch (UnrecoverableKeyException e1) { try { - key = ("Key retreived using password\n" - + keyStore.getKey(alias, keyPassword)); - } catch (UnrecoverableKeyException e1) { - try { - key = ("Key retreived without password\n" - + keyStore.getKey(alias, null)); - } catch (UnrecoverableKeyException e2) { - key = "Key could not be retreived"; - } + key = ("Key retrieved without password\n" + + keyStore.getKey(alias, null)); + } catch (UnrecoverableKeyException e2) { + key = "Key could not be retrieved"; } - out.println(key); + } + out.println(key); + out.println("=========================================="); + Certificate[] chain = keyStore.getCertificateChain(alias); + if (chain == null) { + out.println("No certificate chain associated with key"); out.println("=========================================="); - Certificate[] chain = keyStore.getCertificateChain(alias); - if (chain == null) { - out.println("No certificate chain associated with key"); + } else { + for (int i = 0; i < chain.length; i++) { + out.println("Certificate chain element #" + i); + out.println(chain[i]); out.println("=========================================="); - } else { - for (int i = 0; i < chain.length; i++) { - out.println("Certificate chain element #" + i); - out.println(chain[i]); - out.println("=========================================="); - } } - continue; } - out.println("\tunknown entry type"); + continue; } - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e); + out.println("\tunknown entry type"); } } |