--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/KeyStore/PKCS12/WriteP12Test.java Mon Mar 23 15:37:03 2015 +0800
@@ -0,0 +1,371 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import static java.lang.System.out;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.Enumeration;
+
+/*
+ * @test
+ * @bug 8048618
+ * @summary Write different types p12 key store to Check the write related
+ * APIs.
+ * @run main WriteP12Test
+ */
+
+public class WriteP12Test {
+
+ private static final String IN_KEYSTORE_TYPE = "jks";
+ private static final String IN_KEYSTORE_PRV = "SUN";
+
+ private static final String IN_KEYSTORE_ENDUSER = "keystoreEU.jks.data";
+ private static final String IN_KEYSTORE_CA = "keystoreCA.jks.data";
+ private static final String OUT_KEYSTORE = "outKeyStore.p12";
+
+ private static final String IN_STORE_PASS = "storepass";
+ private static final String IN_KEY_PASS = "keypass";
+
+ private static final String CERT_PATH = System.getProperty("test.src", ".")
+ + File.separator + "certs" + File.separator + "writeP12"
+ + File.separator;
+
+ private static final String CA_CERT_STR = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIDFzCCAf8CBD8+0nAwDQYJKoZIhvcNAQEFBQAwUDELMAkGA1UEBhMCV\n"
+ + "VMxETAPBgNVBAoTCEphdmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0eSBTUU\n"
+ + "UxFzAVBgNVBAMTDlBLQ1MxMiBUZXN0IENBMB4XDTAzMDgxNzAwNTUxMlo\n"
+ + "XDTEzMDgxNDAwNTUxMlowUDELMAkGA1UEBhMCVVMxETAPBgNVBAoTCEph\n"
+ + "dmFTb2Z0MRUwEwYDVQQLEwxTZWN1cml0eSBTUUUxFzAVBgNVBAMTDlBLQ\n"
+ + "1MxMiBUZXN0IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQ\n"
+ + "EAk7Sh+K/yGsmJacZnjfkZfuWxGNJCPW0q69exwoRP+eBHMQwG00yi9aL\n"
+ + "SsZAqNpJSCDvpgySOAUmBd+f8WFhHqJfRVREVfv3mradDKZCjhqtsUI7I\n"
+ + "wRTYYy9clFkeeK4dHaxbuFMPpUu7yQfwSTXgvOA/UJ4kJuGtaYAdTJI4e\n"
+ + "f1mUASo6+dea0UZA/FHCuV7O6z3hr5VHlyhJL2/o/8M5tGBTBISODJSnn\n"
+ + "GNBvtQLNHnWYvs470UAE2BtuCGYh1V/3HAH1tRirS3MBBcb1XnIkiiXR3\n"
+ + "tjaBSB+XhoCfuG8KtInXXFaAnvKfY9mYFw6VJt9JYQpY2VDC7281/Pbz0\n"
+ + "dQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQBzXZ8zHWrnC8/E+N/n2Czhx\n"
+ + "i18YQc2LPWBDLYTTxoFEazWmYLv1k/JT7Nta1qu1quvxXJ4uV1XHbd9NF\n"
+ + "AJWKwtFQEpfv4o6I7qWUPoxnfA+jyqKXxv27z25tzt+Y4xOEhqvO03G0Q\n"
+ + "imhkiNt9MF7L69y2U0/U73+uFNGzdAEDiI9EibvICiOnr1TeQ5GekK3Yb\n"
+ + "k5qe3lviMZPkkSXepTJI8m0AiXCji+eXj97jVLeH+RxeBchBY+uELrqUr\n"
+ + "sVOVWh7IBCqC/V7FqUTkmD1IFlzkkinatpl42s1MbhJId2yQkzaeBRc\n"
+ + "suE63bDEtuRWp9ynMO3QA4Yu85uBRWGzQ1Di\n"
+ + "-----END CERTIFICATE-----";
+ private static final String LEAD_CERT = "-----BEGIN CERTIFICATE-----\n"
+ + "MIICwDCCAaigAwIBAgIEPz7S1jANBgkqhkiG9w0BAQQFADBQMQswCQYDV\n"
+ + "QQGEwJVUzERMA8GA1UEChMISmF2YVNvZnQxFTATBgNVBAsTDFNlY3VyaX\n"
+ + "R5IFNRRTEXMBUGA1UEAxMOUEtDUzEyIFRlc3QgQ0EwHhcNMDAwODA5MDc\n"
+ + "wMDAwWhcNMTAwODA3MDcwMDAwWjBSMQswCQYDVQQGEwJVUzERMA8GA1UE\n"
+ + "ChMISmF2YVNvZnQxFTATBgNVBAsTDFNlY3VyaXR5IFNRRTEZMBcGA1UEA\n"
+ + "xMQUEtDUzEyIFRlc3QgTGVhZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgY\n"
+ + "kCgYEAzq9X2USz/WjDhT+jUyZWqB5h4A33tS11YqH5qYvqjTXjcUI6gOp\n"
+ + "moXMafDG9RHRlIccvp51xLp7Ap3WMrv411lWBttqtZi5c1/DEC1cEM/Sl\n"
+ + "PCk1r2zFbkJu7QKieXeMcrjZEo6LcBHMwQjIpI+up9cr3VjuyqG/olQkU\n"
+ + "mXVuS0CAwEAAaMkMCIwDwYDVR0PAQH/BAUDAweAADAPBgNVHRMBAf8EBT\n"
+ + "ADAQH/MA0GCSqGSIb3DQEBBAUAA4IBAQBhbuim98TWmtv9vSldRE7RvQ8\n"
+ + "FlS0TyZVO7kcSNtfCUE4R76J1ElN74Koc5pQnUtduLeQJs2ao/mEcCZsE\n"
+ + "zVcwI3mSZrSzPhc8s7w5gOQA4TUwVLSSjKgBCaZ7R3+qJ3QeqPJ5O6sFz\n"
+ + "pvBYkgSa4MWptK41jbmT8cwZQJXFCi8WxFFJ+p97F1Ppm3LgmYmtiUP4M\n"
+ + "ZQwOBvpTZWXU0WrqFXpzWQx0mg4SX19fZm4nLcJAerCEUphf8ILagtpQM\n"
+ + "EErT3/jg6mfCdT3Rj055QXPfF4OiRFevPF5a1fZgrCePCukRQZcd7s8K5\n"
+ + "OBIaryuM0MdFtlzxi6XWeUNpVFFHURcy\n"
+ + "-----END CERTIFICATE-----";
+ private static final String END_CERT = "-----BEGIN CERTIFICATE-----\n"
+ + "MIICNjCCAZ+gAwIBAgIEPz7WtzANBgkqhkiG9w0BAQQFADBSMQswCQYDV\n"
+ + "QQGEwJVUzERMA8GA1UEChMISmF2YVNvZnQxFTATBgNVBAsTDFNlY3VyaX\n"
+ + "R5IFNRRTEZMBcGA1UEAxMQUEtDUzEyIFRlc3QgTGVhZDAeFw0wMDA4MDk\n"
+ + "wNzAwMDBaFw0xMDA4MDcwNzAwMDBaMFgxCzAJBgNVBAYTAlVTMREwDwYD\n"
+ + "VQQKEwhKYXZhU29mdDEVMBMGA1UECxMMU2VjdXJpdHkgU1FFMR8wHQYDV\n"
+ + "QQDExZQS0NTMTIgVGVzdCBFbmQgVXNlciAxMIGfMA0GCSqGSIb3DQEBAQ\n"
+ + "UAA4GNADCBiQKBgQDIKomSYomDzH/V63eDQEG7od0DLcnnVZ81pbWhDss\n"
+ + "8gHV2m8pADdRqdihBmnSQEaMW4D3uZ4sFE1LtkQls6hjd7SdOsG5Y24L8\n"
+ + "15jot9a2JcB73H8H0VKirrObL5BZdt7BtASPDnYtW4Spt++YjDoJFxyF0\n"
+ + "HchkavzXaVTlexakwIDAQABoxMwETAPBgNVHQ8BAf8EBQMDB4AAMA0GCS\n"
+ + "qGSIb3DQEBBAUAA4GBAIFA3JXEmb9AXn3RD7t+Mn6DoyVDIy5jsn6xOKT\n"
+ + "JV25I0obpDUzgw4QaAMmM0ZvusOmZ2wZNS8MtyTUgdANyakbzn5SdxbTy\n"
+ + "TLEqQsFbX8UVC38fx5ZM6ExA5YSAvgmXudZpOVC0ATccoZS3JFU8CxSfW\n"
+ + "+Q3IC2MLh+QTg3hUJ5b\n-----END CERTIFICATE-----";
+
+ private final Certificate testerCert;
+ private final Certificate testLeadCert;
+ private final Certificate caCert;
+
+ WriteP12Test() throws CertificateException {
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ caCert = cf.generateCertificate(new ByteArrayInputStream(CA_CERT_STR
+ .getBytes()));
+ testLeadCert = cf.generateCertificate(new ByteArrayInputStream(
+ LEAD_CERT.getBytes()));
+ testerCert = cf.generateCertificate(new ByteArrayInputStream(END_CERT
+ .getBytes()));
+ }
+
+ public static void main(String[] args) throws CertificateException,
+ UnrecoverableKeyException, KeyStoreException,
+ NoSuchProviderException, NoSuchAlgorithmException, IOException {
+ WriteP12Test jstest = new WriteP12Test();
+ out.println("test WriteP12CertChain");
+ /*
+ * WriteP12CertChain: This test creates a p12 keystore contains one
+ * entry with private key and a certificate chains contains three
+ * certificates in the order of user->lead->ca. This case expects to
+ * pass.
+ */
+ jstest.test(new Certificate[] { jstest.testerCert, jstest.testLeadCert,
+ jstest.caCert }, IN_KEYSTORE_ENDUSER, "pkcs12testenduser1",
+ "pass", "pass");
+
+ /*
+ * WriteP12CertChainBad: same as WriteP12CertChain but chains order is
+ * user-ca-lead, the order is wrong so expects to fail.
+ */
+ out.println("test WriteP12CertChainBad");
+ try {
+ jstest.test(new Certificate[] { jstest.testerCert, jstest.caCert,
+ jstest.testLeadCert }, IN_KEYSTORE_ENDUSER,
+ "pkcs12testenduser1", "pass", "pass");
+ throw new RuntimeException(
+ " Certificate chain is not valid, test should not pass."
+ + " Test failed.");
+ } catch (KeyStoreException e) {
+ e.printStackTrace();
+ out.println(" Certificate chain is not valid,exception is"
+ + " expected. Test passed.");
+ }
+ /*
+ * WriteP12PrivateKey:This test creates a p12 contains a self-signed
+ * cert and private key,expects no exception
+ */
+ out.println("test WriteP12PrivateKey");
+ jstest.test(null, IN_KEYSTORE_ENDUSER, "pkcs12testenduser1", "pass",
+ "pass");
+
+ /*
+ * WriteP12TwoEntry: This test creates a p12 keystore with different
+ * storepass and keypass, and contains two entries.
+ */
+ out.println("test WriteP12TwoEntry");
+ jstest.testTwoEntry(IN_KEYSTORE_ENDUSER, IN_KEYSTORE_CA,
+ "pkcs12testenduser1", "pass", "pass");
+ /*
+ * WriteP12TwoPass: This test creates a p12 keystore with different
+ * storepass and keypass, and contains one entry with private key and a
+ * certificate
+ */
+ out.println("test WriteP12TwoPass");
+ jstest.test(null, IN_KEYSTORE_CA, "pkcs12testCA", "storepass",
+ "keypass");
+ }
+
+ private void test(Certificate certs[], String inKeyStorePath,
+ String userAlias, String outStorePass, String outKeyPass)
+ throws KeyStoreException, NoSuchProviderException, IOException,
+ CertificateException, UnrecoverableKeyException,
+ NoSuchAlgorithmException {
+ // init output key store
+ KeyStore outputKeyStore = KeyStore.getInstance("pkcs12", "SunJSSE");
+ outputKeyStore.load(null, null);
+ try (FileOutputStream fout = new FileOutputStream(OUT_KEYSTORE)) {
+ // KeyStore have encoded by Base64.getMimeEncoder().encode(),need
+ // decode first.
+ byte[] input = Files.readAllBytes(Paths.get(CERT_PATH,
+ inKeyStorePath));
+ ByteArrayInputStream arrayIn = new ByteArrayInputStream(Base64
+ .getMimeDecoder().decode(input));
+ // input key store
+ KeyStore inputKeyStore = KeyStore.getInstance(IN_KEYSTORE_TYPE,
+ IN_KEYSTORE_PRV);
+ inputKeyStore.load(arrayIn, IN_STORE_PASS.toCharArray());
+ // add key/certificate to output key store
+ Key key = inputKeyStore
+ .getKey(userAlias, IN_KEY_PASS.toCharArray());
+ out.println("Input Key Algorithm " + key.getAlgorithm());
+ out.println("====Input Certs=====");
+ if (certs == null) {
+ certs = new Certificate[] { inputKeyStore
+ .getCertificate(userAlias) };
+ }
+ for (Certificate cert : certs) {
+ out.println(((X509Certificate) cert).getSubjectDN());
+ }
+ outputKeyStore.setKeyEntry(userAlias, key,
+ outKeyPass.toCharArray(), certs);
+ Certificate retCerts[] = outputKeyStore
+ .getCertificateChain(userAlias);
+ out.println("====Output Certs=====");
+ for (Certificate retCert : retCerts) {
+ out.println(((X509Certificate) retCert).getSubjectDN());
+ }
+ out.println("====Output Key Algorithm=====");
+ Key outKey = outputKeyStore.getKey(userAlias,
+ outKeyPass.toCharArray());
+ out.println(outKey.getAlgorithm());
+
+ if (!key.equals(outKey)) {
+ throw new RuntimeException("key don't match");
+ }
+ if (!Arrays.equals(certs, retCerts)) {
+ throw new RuntimeException("certs don't match");
+ }
+ // save output
+ outputKeyStore.store(fout, outStorePass.toCharArray());
+ // test output
+ testKeyStore(outputKeyStore, outKeyPass.toCharArray());
+ }
+ }
+
+ private void testTwoEntry(String inKeyStoreOnePath,
+ String inKeyStoreTwoPath, String userAlias, String outStorePass,
+ String outKeyPass) throws KeyStoreException,
+ NoSuchProviderException, NoSuchAlgorithmException,
+ CertificateException, IOException, UnrecoverableKeyException {
+ // initial KeyStore
+ KeyStore outputKeyStore = KeyStore.getInstance("pkcs12", "SunJSSE");
+ try (FileOutputStream fout = new FileOutputStream(OUT_KEYSTORE);) {
+ outputKeyStore.load(null, null);
+ KeyStore inputKeyStoreOne, inputKeyStoreTwo;
+ inputKeyStoreOne = KeyStore.getInstance(IN_KEYSTORE_TYPE,
+ IN_KEYSTORE_PRV);
+ // KeyStore have encoded by Base64.getMimeEncoder().encode(),need
+ // decode first.
+ byte[] inputBytes = Files.readAllBytes(Paths.get(CERT_PATH,
+ inKeyStoreOnePath));
+ ByteArrayInputStream arrayIn = new ByteArrayInputStream(Base64
+ .getMimeDecoder().decode(inputBytes));
+ // input key store
+ inputKeyStoreOne.load(arrayIn, IN_STORE_PASS.toCharArray());
+
+ inputBytes = Files.readAllBytes(Paths.get(CERT_PATH,
+ inKeyStoreTwoPath));
+ arrayIn = new ByteArrayInputStream(Base64.getMimeDecoder().decode(
+ inputBytes));
+ inputKeyStoreTwo = KeyStore.getInstance(IN_KEYSTORE_TYPE,
+ IN_KEYSTORE_PRV);
+ inputKeyStoreTwo.load(arrayIn, IN_STORE_PASS.toCharArray());
+
+ // add key/certificate to output key store
+ out.println("====First Entry=====");
+ Key inputKey = inputKeyStoreOne.getKey(userAlias,
+ IN_KEY_PASS.toCharArray());
+ Certificate cert = inputKeyStoreOne.getCertificate(userAlias);
+ Certificate certs[] = new Certificate[1];
+ certs[0] = cert;
+
+ out.println("====Input1 Key=====");
+ out.println(inputKey.getAlgorithm());
+ out.println("====Input1 Certs=====");
+ out.println("Certificate :");
+ out.println(((X509Certificate) cert).getSubjectDN());
+ outputKeyStore.setKeyEntry("USER", inputKey,
+ outKeyPass.toCharArray(), certs);
+ out.println("====Second Entry=====");
+ String caAlias = "pkcs12testca";
+ inputKey = inputKeyStoreTwo.getKey(caAlias,
+ IN_KEY_PASS.toCharArray());
+ cert = inputKeyStoreTwo.getCertificate(caAlias);
+ certs[0] = cert;
+ out.println("====Input2 Key=====");
+ out.println(inputKey.getAlgorithm());
+ out.println("====Input2 Certs=====");
+ out.println("Certificate :");
+ out.println(((X509Certificate) cert).getSubjectDN());
+ outputKeyStore.setKeyEntry("CA", inputKey,
+ outKeyPass.toCharArray(), certs);
+ // save output
+ outputKeyStore.store(fout, outStorePass.toCharArray());
+ // test output
+ testKeyStore(outputKeyStore, outKeyPass.toCharArray());
+ }
+ }
+
+ private void testKeyStore(KeyStore inputKeyStore, char[] keypass)
+ throws KeyStoreException, UnrecoverableKeyException,
+ NoSuchAlgorithmException {
+ out.println("========== Key Store ==========");
+ out.println("getProvider : " + inputKeyStore.getProvider());
+ out.println("getType : " + inputKeyStore.getType());
+ out.println("getDefaultType : " + KeyStore.getDefaultType());
+
+ int idx = 0;
+ Enumeration<String> e = inputKeyStore.aliases();
+ String alias;
+ while (e.hasMoreElements()) {
+ alias = e.nextElement();
+ if (!inputKeyStore.containsAlias(alias)) {
+ throw new RuntimeException("Alias not found");
+ }
+ out.println("Alias " + idx + " : " + alias);
+ out.println("getCreationDate : "
+ + inputKeyStore.getCreationDate(alias));
+ X509Certificate cert = (X509Certificate) inputKeyStore
+ .getCertificate(alias);
+ out.println("getCertificate : " + cert.getSubjectDN());
+ String retAlias = inputKeyStore.getCertificateAlias(cert);
+ if (!retAlias.equals(alias)) {
+ throw new RuntimeException("Alias mismatch, actually "
+ + retAlias + ", expected " + alias);
+ }
+ out.println("getCertificateAlias : " + retAlias);
+ Certificate[] certs = inputKeyStore.getCertificateChain(alias);
+ int i = 0;
+ for (Certificate certification : certs) {
+ out.println("getCertificateChain " + i
+ + ((X509Certificate) certification).getSubjectDN());
+ i++;
+ }
+ if (inputKeyStore.isCertificateEntry(alias)) {
+ throw new RuntimeException(
+ "inputKeystore should not be certEntry because this"
+ + " keystore only contain key pair entries.");
+ }
+ if (!inputKeyStore.isKeyEntry(alias)) {
+ throw new RuntimeException("Entry type unknown.");
+ }
+ idx++;
+ }
+ int size = inputKeyStore.size();
+ if (idx != size) {
+ throw new RuntimeException("Size not match, actually " + idx
+ + ", expected " + size);
+ }
+ }
+
+}