1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package jdk.test.lib.security; 25 26 import java.io.ByteArrayInputStream; 27 import java.io.FileInputStream; 28 import java.io.InputStream; 29 import java.security.KeyStore; 30 import java.security.PrivateKey; 31 import java.security.cert.Certificate; 32 import java.util.ArrayList; 33 import java.util.Base64; 34 import java.util.List; 35 36 /* 37 * Utilities for creating key store. 38 */ 39 public class KeyStoreUtils { 40 41 private static final String DEFAULT_TYPE = KeyStore.getDefaultType(); 42 43 /** 44 * Create key store with a given input stream. 45 * 46 * @param type the key store type 47 * @param input the input stream containing a key store 48 * @param password the password used to check the integrity of the key store 49 * @return the key store 50 * @throws Exception on errors 51 */ 52 public static KeyStore loadKeyStore(String type, InputStream input, 53 String password) throws Exception { 54 KeyStore keyStore = KeyStore.getInstance(type); 55 try { 56 keyStore.load(input, 57 password == null ? null : password.toCharArray()); 58 return keyStore; 59 } finally { 60 if (input != null) { 61 input.close(); 62 } 63 } 64 } 65 66 /** 67 * Create key store with a given input stream. 68 * 69 * @param input the input stream containing a key store 70 * @param password the password used to check the integrity of the key store 71 * @return the key store 72 * @throws Exception on errors 73 */ 74 public static KeyStore loadKeyStore(InputStream input, String password) 75 throws Exception { 76 return loadKeyStore(DEFAULT_TYPE, input, password); 77 } 78 79 /** 80 * Create key store with given Base64-encoded string. 81 * 82 * @param keyStoreBase64 the Base64-encoded string containing a key store 83 * @param password the password used to check the integrity of the key store 84 * @return the key store 85 * @throws Exception on errors 86 */ 87 public static KeyStore loadKeyStoreBase64(String keyStoreBase64, 88 String password) throws Exception { 89 return loadKeyStore(DEFAULT_TYPE, new ByteArrayInputStream( 90 Base64.getDecoder().decode(keyStoreBase64)), password); 91 } 92 93 /** 94 * Create key store with a given file. 95 * 96 * @param type the key store type 97 * @param path the path to file containing a key store 98 * @param password the password used to check the integrity of the key store 99 * @return the key store 100 * @throws Exception on errors 101 */ 102 public static KeyStore loadKeyStore(String type, String path, 103 String password) throws Exception { 104 return loadKeyStore(type, new FileInputStream(path), password); 105 } 106 107 /** 108 * Create key store with a given file. 109 * 110 * @param path the path to file containing a key store 111 * @param password the password used to check the integrity of the key store 112 * @return the key store 113 * @throws Exception on errors 114 */ 115 public static KeyStore loadKeyStore(String path, String password) 116 throws Exception { 117 return loadKeyStore(DEFAULT_TYPE, path, password); 118 } 119 120 /** 121 * Create trust store with given certificates. 122 * 123 * @param type the key store type 124 * @param certStrs the certificates added to the trust store 125 * @return the trust store 126 * @throws Exception on errors 127 */ 128 public static KeyStore createTrustStore(String type, String[] certStrs) 129 throws Exception { 130 KeyStore trustStore = initKeyStore(type); 131 132 for (int i = 0; i < certStrs.length; i++) { 133 trustStore.setCertificateEntry("trust-" + i, 134 CertUtils.getCertFromString(certStrs[i])); 135 } 136 137 return trustStore; 138 } 139 140 /** 141 * Create trust store with given certificates. 142 * 143 * @param certStrs the certificates added to the trust store 144 * @return the trust store 145 * @throws Exception on errors 146 */ 147 public static KeyStore createTrustStore(String[] certStrs) 148 throws Exception { 149 return createTrustStore(DEFAULT_TYPE, certStrs); 150 } 151 152 /** 153 * Create key store with given entries. 154 * 155 * @param type the key store type 156 * @param entries the key entries added to the key store 157 * @return the key store 158 * @throws Exception on errors 159 */ 160 public static KeyStore createKeyStore(String type, KeyEntry[] entries) 161 throws Exception { 162 KeyStore keyStore = initKeyStore(type); 163 164 for (int i = 0; i < entries.length; i++) { 165 KeyEntry entry = entries[i]; 166 PrivateKey key = CertUtils.getKeyFromString( 167 entry.keyAlgo, entry.keyStr); 168 char[] password = entry.password == null 169 ? null 170 : entry.password.toCharArray(); 171 Certificate[] chain = new Certificate[entry.certStrs.length]; 172 for (int j = 0; j < chain.length; j++) { 173 chain[j] = CertUtils.getCertFromString(entry.certStrs[j]); 174 } 175 176 keyStore.setKeyEntry("cert-" + i, key, password, chain); 177 } 178 179 return keyStore; 180 } 181 182 /** 183 * Create key store with given entries. 184 * 185 * @param entries the key entries added to the key store 186 * @return the key store 187 * @throws Exception on errors 188 */ 189 public static KeyStore createKeyStore(KeyEntry[] entries) 190 throws Exception { 191 return createKeyStore(DEFAULT_TYPE, entries); 192 } 193 194 /** 195 * Create key store with given private keys and associated certificate chains. 196 * Note that here one chain contains only one certificate. If a chain needs 197 * to contain multiple certificates, please use the following methods: 198 * createKeyStore(String type, KeyEntry[] entries); 199 * createKeyStore(KeyEntry[] entries) 200 * 201 * @param type the key store type 202 * @param keyAlgos the key algorithm array 203 * @param keyStrs the PEM-encoded PKCS8 key string array 204 * @param passwords the key-associated password array 205 * @param certStrs the key-associated certificate array 206 * @return the key store 207 * @throws Exception on errors 208 */ 209 public static KeyStore createKeyStore(String type, String[] keyAlgos, 210 String[] keyStrs, String[] passwords, String[] certStrs) 211 throws Exception { 212 KeyEntry[] entries = new KeyEntry[keyStrs.length]; 213 for (int i = 0; i < entries.length; i++) { 214 entries[i] = new KeyEntry( 215 keyAlgos[i], 216 keyStrs[i], 217 passwords == null ? null : passwords[i], 218 new String[] { certStrs[i] }); 219 } 220 return createKeyStore(type, entries); 221 } 222 223 /** 224 * Create key store with given private keys and associated certificate chains. 225 * Note that here one chain contains only one certificate. If a chain needs 226 * to contain multiple certificates, please use the following methods: 227 * createKeyStore(String type, KeyEntry[] entries); 228 * createKeyStore(KeyEntry[] entries) 229 * 230 * @param keyAlgos the key algorithm array 231 * @param keyStrs the PEM-encoded PKCS8 key string array 232 * @param passwords the key-associated password array 233 * @param certStrs the key-associated certificate array 234 * @return the key store 235 * @throws Exception on errors 236 */ 237 public static KeyStore createKeyStore(String[] keyAlgos, String[] keyStrs, 238 String[] passwords, String[] certStrs) throws Exception { 239 return createKeyStore(DEFAULT_TYPE, keyAlgos, keyStrs, passwords, 240 certStrs); 241 } 242 243 private static KeyStore initKeyStore(String type) throws Exception { 244 KeyStore keyStore = KeyStore.getInstance(type); 245 keyStore.load(null, null); 246 return keyStore; 247 } 248 249 /** 250 * The default trust store that contains RSA, ECDSA, RSASSA-PSS and DSA 251 * certificates. 252 */ 253 public static KeyStore defaultTrustStore() throws Exception { 254 return createTrustStore( 255 new String[] { CertUtils.RSA_CERT, CertUtils.ECDSA_CERT, 256 CertUtils.RSASSAPSS_CERT, CertUtils.DSA_CERT }); 257 } 258 259 /** 260 * The default key store that contains RSA, ECDSA, RSASSA-PSS and DSA 261 * certificates. 262 */ 263 public static KeyStore defaultKeyStore() throws Exception { 264 List<KeyEntry> entries = new ArrayList<>(); 265 entries.add(new KeyEntry("RSA", CertUtils.RSA_KEY, 266 new String[] { CertUtils.RSA_CERT })); 267 entries.add(new KeyEntry("EC", CertUtils.ECDSA_KEY, 268 new String[] { CertUtils.ECDSA_CERT })); 269 entries.add(new KeyEntry("RSASSA-PSS", CertUtils.RSASSAPSS_KEY, 270 new String[] { CertUtils.RSASSAPSS_CERT })); 271 entries.add(new KeyEntry("DSA", CertUtils.DSA_KEY, 272 new String[] { CertUtils.DSA_CERT })); 273 return createKeyStore(entries.toArray(new KeyEntry[entries.size()])); 274 } 275 }