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