1 /* 2 * Copyright (c) 2003, 2017, 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 /** 25 * 26 * @author Sean Mullan 27 * @author Steve Hanna 28 * 29 */ 30 import java.io.ByteArrayInputStream; 31 import java.io.ByteArrayOutputStream; 32 import java.io.File; 33 import java.io.FileInputStream; 34 import java.io.InputStream; 35 import java.io.IOException; 36 import java.security.cert.CertificateException; 37 import java.security.cert.CertificateFactory; 38 import java.security.cert.CertPath; 39 import java.security.cert.CertPathBuilder; 40 import java.security.cert.CertPathValidator; 41 import java.security.cert.CertStore; 42 import java.security.cert.CollectionCertStoreParameters; 43 import java.security.cert.CRLException; 44 import java.security.cert.PKIXBuilderParameters; 45 import java.security.cert.PKIXCertPathBuilderResult; 46 import java.security.cert.PKIXCertPathValidatorResult; 47 import java.security.cert.PKIXParameters; 48 import java.security.cert.X509Certificate; 49 import java.security.cert.X509CRL; 50 import java.util.ArrayList; 51 import java.util.HashSet; 52 import java.util.List; 53 import java.util.Set; 54 55 /** 56 * Static utility methods useful for testing certificate/certpath APIs. 57 */ 58 public class CertUtils { 59 60 private CertUtils() {} 61 62 /** 63 * Get a DER-encoded X.509 certificate from a file. 64 * 65 * @param certFilePath path to file containing DER-encoded certificate 66 * @return the X509Certificate 67 * @throws CertificateException if the certificate type is not supported 68 * or cannot be parsed 69 * @throws IOException if the file cannot be opened 70 */ 71 public static X509Certificate getCertFromFile(String certFilePath) 72 throws CertificateException, IOException { 73 File certFile = new File(System.getProperty("test.src", "."), 74 certFilePath); 75 try (FileInputStream fis = new FileInputStream(certFile)) { 76 return (X509Certificate) 77 CertificateFactory.getInstance("X.509") 78 .generateCertificate(fis); 79 } 80 } 81 82 /** 83 * Get a PEM-encoded X.509 certificate from a string. 84 * 85 * @param cert string containing the PEM-encoded certificate 86 * @return the X509Certificate 87 * @throws CertificateException if the certificate type is not supported 88 * or cannot be parsed 89 */ 90 public static X509Certificate getCertFromString(String cert) 91 throws CertificateException { 92 byte[] certBytes = cert.getBytes(); 93 ByteArrayInputStream bais = new ByteArrayInputStream(certBytes); 94 return (X509Certificate) 95 CertificateFactory.getInstance("X.509").generateCertificate(bais); 96 } 97 98 /** 99 * Get a DER-encoded X.509 CRL from a file. 100 * 101 * @param crlFilePath path to file containing DER-encoded CRL 102 * @return the X509CRL 103 * @throws CertificateException if the crl type is not supported 104 * @throws CRLException if the crl cannot be parsed 105 * @throws IOException if the file cannot be opened 106 */ 107 public static X509CRL getCRLFromFile(String crlFilePath) 108 throws CertificateException, CRLException, IOException { 109 File crlFile = new File(System.getProperty("test.src", "."), 110 crlFilePath); 111 try (FileInputStream fis = new FileInputStream(crlFile)) { 112 return (X509CRL) 113 CertificateFactory.getInstance("X.509").generateCRL(fis); 114 } 115 } 116 117 /** 118 * Get a PEM-encoded X.509 crl from a string. 119 * 120 * @param crl string containing the PEM-encoded crl 121 * @return the X509CRL 122 * @throws CertificateException if the crl type is not supported 123 * @throws CRLException if the crl cannot be parsed 124 */ 125 public static X509CRL getCRLFromString(String crl) 126 throws CertificateException, CRLException { 127 byte[] crlBytes = crl.getBytes(); 128 ByteArrayInputStream bais = new ByteArrayInputStream(crlBytes); 129 return (X509CRL) 130 CertificateFactory.getInstance("X.509").generateCRL(bais); 131 } 132 133 /** 134 * Read a bunch of certs from files and create a CertPath from them. 135 * 136 * @param fileNames an array of <code>String</code>s that are file names 137 * @throws Exception on error 138 */ 139 public static CertPath buildPath(String [] fileNames) throws Exception { 140 return buildPath("", fileNames); 141 } 142 143 /** 144 * Read a bunch of certs from files and create a CertPath from them. 145 * 146 * @param relPath relative path containing certs (must end in 147 * file.separator) 148 * @param fileNames an array of <code>String</code>s that are file names 149 * @throws Exception on error 150 */ 151 public static CertPath buildPath(String relPath, String [] fileNames) 152 throws Exception { 153 List<X509Certificate> list = new ArrayList<X509Certificate>(); 154 for (int i = 0; i < fileNames.length; i++) { 155 list.add(0, getCertFromFile(relPath + fileNames[i])); 156 } 157 CertificateFactory cf = CertificateFactory.getInstance("X509"); 158 return(cf.generateCertPath(list)); 159 } 160 161 162 /** 163 * Read a bunch of certs from files and create a CertStore from them. 164 * 165 * @param fileNames an array of <code>String</code>s that are file names 166 * @return the <code>CertStore</code> created 167 * @throws Exception on error 168 */ 169 public static CertStore createStore(String [] fileNames) throws Exception { 170 return createStore("", fileNames); 171 } 172 173 /** 174 * Read a bunch of certs from files and create a CertStore from them. 175 * 176 * @param relPath relative path containing certs (must end in 177 * file.separator) 178 * @param fileNames an array of <code>String</code>s that are file names 179 * @return the <code>CertStore</code> created 180 * @throws Exception on error 181 */ 182 public static CertStore createStore(String relPath, String [] fileNames) 183 throws Exception { 184 Set<X509Certificate> certs = new HashSet<X509Certificate>(); 185 for (int i = 0; i < fileNames.length; i++) { 186 certs.add(getCertFromFile(relPath + fileNames[i])); 187 } 188 return CertStore.getInstance("Collection", 189 new CollectionCertStoreParameters(certs)); 190 } 191 192 /** 193 * Read a bunch of CRLs from files and create a CertStore from them. 194 * 195 * @param fileNames an array of <code>String</code>s that are file names 196 * @return the <code>CertStore</code> created 197 * @throws Exception on error 198 */ 199 public static CertStore createCRLStore(String [] fileNames) 200 throws Exception { 201 return createCRLStore("", fileNames); 202 } 203 204 /** 205 * Read a bunch of CRLs from files and create a CertStore from them. 206 * 207 * @param relPath relative path containing CRLs (must end in file.separator) 208 * @param fileNames an array of <code>String</code>s that are file names 209 * @return the <code>CertStore</code> created 210 * @throws Exception on error 211 */ 212 public static CertStore createCRLStore(String relPath, String [] fileNames) 213 throws Exception { 214 Set<X509CRL> crls = new HashSet<X509CRL>(); 215 for (int i = 0; i < fileNames.length; i++) { 216 crls.add(getCRLFromFile(relPath + fileNames[i])); 217 } 218 return CertStore.getInstance("Collection", 219 new CollectionCertStoreParameters(crls)); 220 } 221 222 /** 223 * Perform a PKIX path build. On failure, throw an exception. 224 * 225 * @param params PKIXBuilderParameters to use in validation 226 * @throws Exception on error 227 */ 228 public static PKIXCertPathBuilderResult build(PKIXBuilderParameters params) 229 throws Exception { 230 CertPathBuilder builder = 231 CertPathBuilder.getInstance("PKIX"); 232 return (PKIXCertPathBuilderResult) builder.build(params); 233 } 234 235 /** 236 * Perform a PKIX validation. On failure, throw an exception. 237 * 238 * @param path CertPath to validate 239 * @param params PKIXParameters to use in validation 240 * @throws Exception on error 241 */ 242 public static PKIXCertPathValidatorResult validate 243 (CertPath path, PKIXParameters params) throws Exception { 244 CertPathValidator validator = 245 CertPathValidator.getInstance("PKIX"); 246 return (PKIXCertPathValidatorResult) validator.validate(path, params); 247 } 248 249 /* 250 * Reads the entire input stream into a byte array. 251 */ 252 private static byte[] getTotalBytes(InputStream is) throws IOException { 253 byte[] buffer = new byte[8192]; 254 ByteArrayOutputStream baos = new ByteArrayOutputStream(2048); 255 int n; 256 baos.reset(); 257 while ((n = is.read(buffer, 0, buffer.length)) != -1) { 258 baos.write(buffer, 0, n); 259 } 260 return baos.toByteArray(); 261 } 262 }