1/* 2 * Copyright (c) 2008, 2014, 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 24import static java.lang.System.out; 25 26import java.io.ByteArrayInputStream; 27import java.io.File; 28import java.io.FileOutputStream; 29import java.nio.file.Files; 30import java.nio.file.Paths; 31import java.security.Key; 32import java.security.KeyStore; 33import java.security.KeyStoreException; 34import java.security.NoSuchAlgorithmException; 35import java.security.UnrecoverableKeyException; 36import java.security.cert.Certificate; 37import java.util.Arrays; 38import java.util.Base64; 39import java.util.Enumeration; 40 41/* 42 * @test 43 * @bug 8048619 44 * @author Bill Situ 45 * @summary Test converting keystore from jceks to P12 and from P12 to other 46 * (jceks,jks). including following test cases: 47 * Read jceks key store and convert to the p12 key store, then compare entries 48 * in the two key stores. 49 * Read p12 key store and convert to the jceks key store, then compare entries 50 * in the two key stores. 51 * Read p12 key store (contains only private key and a self-signed certificate) 52 * and convert to the jceks key store, then compare entries of two key stores. 53 * Read p12 key store (contains 2 entries) and convert to the jceks key store, 54 * then compare entries in the two key stores. 55 * Read p12 key store (entry password and key store password are different) and 56 * convert to the jceks key store, then compare entries in the two key stores. 57 * Read p12 key store and convert to the jks key store, then compare entries 58 * in the two key stores. 59 * Read p12 key store (contains only private key and a self-signed certificate) 60 * and convert to the jks key store, then compare entries in the two key stores. 61 * Read p12 key store (contains 2 entries) and convert to the jks key store, 62 * then compare entries in the two key stores. 63 * Read p12 key store (entry password and key store password are different) and 64 * convert to the jks key store, then compare entries in the two key stores. 65 */ 66 67public class ConvertP12Test { 68 69 private static final String SUN_JSSE = "SunJSSE"; 70 private static final String SUN_JCE = "SunJCE"; 71 private static final String SUN = "SUN"; 72 private static final String PKCS12 = "pkcs12"; 73 private static final String JCE_KS = "JceKS"; 74 private static final String JKS = "JKS"; 75 76 public static void main(String args[]) throws Exception { 77 78 ConvertP12Test jstest = new ConvertP12Test(); 79 80 jstest.driver("JceksToP12", "keystoreCA.jceks.data", JCE_KS, SUN_JCE, 81 "storepass", "keypass", PKCS12, SUN_JSSE); 82 83 jstest.driver("P12ToJceks_Chain", "ie_jceks_chain.pfx.data", PKCS12, 84 SUN_JSSE, "pass", "pass", JCE_KS, SUN_JCE); 85 86 jstest.driver("P12ToJceks_SelfSigned", "jdk_jceks_selfsigned.p12.data", 87 PKCS12, SUN_JSSE, "pass", "pass", JCE_KS, SUN_JCE); 88 89 jstest.driver("P12ToJceks_TwoEntry", "jdk_jceks_twoentry.p12.data", 90 PKCS12, SUN_JSSE, "pass", "pass", JCE_KS, SUN_JCE); 91 92 jstest.driver("P12ToJceks_TwoPass", "jdk_jceks_twopass.p12.data", 93 PKCS12, SUN_JSSE, "storepass", "keypass", JCE_KS, SUN_JCE); 94 95 jstest.driver("P12ToJks_Chain", "ie_jks_chain.pfx.data", PKCS12, 96 SUN_JSSE, "pass", "pass", JKS, SUN); 97 98 jstest.driver("P12ToJks_SelfSigned", "jdk_jks_selfsigned.p12.data", 99 PKCS12, SUN_JSSE, "pass", "pass", JKS, SUN); 100 101 jstest.driver("P12ToJks_TwoEntry", "jdk_jks_twoentry.p12.data", PKCS12, 102 SUN_JSSE, "pass", "pass", JKS, SUN); 103 104 jstest.driver("P12ToJks_TwoPass", "jdk_jks_twopass.p12.data", PKCS12, 105 SUN_JSSE, "storepass", "keypass", JKS, SUN); 106 107 } 108 109 private void driver(String testCase, String inKeyStore, 110 String inKeyStoreType, String inKeyStoreTypePrv, 111 String inStorePass, String inKeyPass, String outKeyStoreType, 112 String outKeyStorePrv) throws Exception { 113 114 String outStorePass = "pass"; 115 String outKeyPass = "pass"; 116 KeyStore inputKeyStore, outputKeyStore; 117 118 out.println("Testing " + testCase); 119 String keystorePath = System.getProperty("test.src", ".") 120 + File.separator + "certs" + File.separator + "convertP12"; 121 out.println("Output KeyStore : " + inKeyStore + ".out"); 122 String outKeyStoreName = inKeyStore + ".out"; 123 try (FileOutputStream fout = new FileOutputStream(outKeyStoreName);) { 124 inputKeyStore = KeyStore.getInstance(inKeyStoreType, 125 inKeyStoreTypePrv); 126 127 // KeyStore have encoded by Base64.getMimeEncoder().encode(),need 128 // decode first. 129 byte[] input = Files.readAllBytes(Paths.get(keystorePath, 130 inKeyStore)); 131 ByteArrayInputStream arrayIn = new ByteArrayInputStream(Base64 132 .getMimeDecoder().decode(input)); 133 134 out.println("Input KeyStore : " + inKeyStore); 135 136 inputKeyStore.load(arrayIn, inStorePass.toCharArray()); 137 138 outputKeyStore = KeyStore.getInstance(outKeyStoreType, 139 outKeyStorePrv); 140 outputKeyStore.load(null, null); 141 142 run(inputKeyStore, outputKeyStore, inKeyPass, outKeyPass); 143 144 outputKeyStore.store(fout, outStorePass.toCharArray()); 145 146 // for P12ToJks_TwoEntry test case will test includes each other, 147 // others just test compareKeystore 148 if (testCase.contains("TwoEntry")) { 149 150 compareKeyStore(inputKeyStore, outputKeyStore, inKeyPass, 151 outKeyPass, 2); 152 compareKeyStore(outputKeyStore, inputKeyStore, outKeyPass, 153 inKeyPass, 2); 154 } else { 155 compareKeyStore(inputKeyStore, outputKeyStore, inKeyPass, 156 outKeyPass, 1); 157 } 158 out.println("Test " + testCase + " STATUS: Pass!!"); 159 } catch (Exception ex) { 160 out.println("Test " + testCase + " STATUS: failed with exception: " 161 + ex.getMessage()); 162 throw ex; 163 } 164 } 165 166 private void run(KeyStore inputKeyStore, KeyStore outputKeyStore, 167 String inKeyPass, String outKeyPass) throws Exception { 168 Enumeration<String> e = inputKeyStore.aliases(); 169 String alias; 170 while (e.hasMoreElements()) { 171 alias = e.nextElement(); 172 Certificate[] certs = inputKeyStore.getCertificateChain(alias); 173 174 boolean isCertEntry = inputKeyStore.isCertificateEntry(alias); 175 // Test KeyStore only contain key pair entries. 176 if (isCertEntry == true) { 177 throw new RuntimeException( 178 "inputKeystore should not be certEntry because test" 179 + " keystore only contain key pair entries" 180 + " for alias:" + alias); 181 } 182 183 boolean isKeyEntry = inputKeyStore.isKeyEntry(alias); 184 Key key = null; 185 if (isKeyEntry) { 186 key = inputKeyStore.getKey(alias, inKeyPass.toCharArray()); 187 } else { 188 throw new RuntimeException("Entry type unknown for alias:" 189 + alias); 190 } 191 outputKeyStore.setKeyEntry(alias, key, outKeyPass.toCharArray(), 192 certs); 193 } 194 } 195 196 private void compareKeyStore(KeyStore a, KeyStore b, String inKeyPass, 197 String outKeyPass, int keyStoreSize) throws Exception { 198 if (a.size() != keyStoreSize || b.size() != keyStoreSize) { 199 throw new RuntimeException("size not match or size not equal to " 200 + keyStoreSize); 201 } 202 203 Enumeration<String> eA = a.aliases(); 204 while (eA.hasMoreElements()) { 205 String aliasA = eA.nextElement(); 206 207 if (!b.containsAlias(aliasA)) { 208 throw new RuntimeException("alias not match for alias:" 209 + aliasA); 210 } 211 212 compareKeyEntry(a, b, inKeyPass, outKeyPass, aliasA); 213 } 214 } 215 216 private void compareKeyEntry(KeyStore a, KeyStore b, String aPass, 217 String bPass, String alias) throws KeyStoreException, 218 UnrecoverableKeyException, NoSuchAlgorithmException { 219 Certificate[] certsA = a.getCertificateChain(alias); 220 Certificate[] certsB = b.getCertificateChain(alias); 221 222 if (!Arrays.equals(certsA, certsB)) { 223 throw new RuntimeException("Certs don't match for alias:" + alias); 224 } 225 226 Key keyA = a.getKey(alias, aPass.toCharArray()); 227 Key keyB = b.getKey(alias, bPass.toCharArray()); 228 229 if (!keyA.equals(keyB)) { 230 throw new RuntimeException( 231 "Key don't match for alias:" + alias); 232 } 233 } 234} 235