001 /*
002 * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package java.security.cert;
027
028 import java.io.InputStream;
029 import java.util.Collection;
030 import java.util.Iterator;
031 import java.util.List;
032 import java.security.Provider;
033 import java.security.Security;
034 import java.security.AccessController;
035 import java.security.PrivilegedAction;
036 import java.security.NoSuchAlgorithmException;
037 import java.security.NoSuchProviderException;
038
039 import sun.security.jca.*;
040 import sun.security.jca.GetInstance.Instance;
041
042 /**
043 * This class defines the functionality of a certificate factory, which is
044 * used to generate certificate, certification path (<code>CertPath</code>)
045 * and certificate revocation list (CRL) objects from their encodings.
046 *
047 * <p>For encodings consisting of multiple certificates, use
048 * <code>generateCertificates</code> when you want to
049 * parse a collection of possibly unrelated certificates. Otherwise,
050 * use <code>generateCertPath</code> when you want to generate
051 * a <code>CertPath</code> (a certificate chain) and subsequently
052 * validate it with a <code>CertPathValidator</code>.
053 *
054 * <p>A certificate factory for X.509 must return certificates that are an
055 * instance of <code>java.security.cert.X509Certificate</code>, and CRLs
056 * that are an instance of <code>java.security.cert.X509CRL</code>.
057 *
058 * <p>The following example reads a file with Base64 encoded certificates,
059 * which are each bounded at the beginning by -----BEGIN CERTIFICATE-----, and
060 * bounded at the end by -----END CERTIFICATE-----. We convert the
061 * <code>FileInputStream</code> (which does not support <code>mark</code>
062 * and <code>reset</code>) to a <code>BufferedInputStream</code> (which
063 * supports those methods), so that each call to
064 * <code>generateCertificate</code> consumes only one certificate, and the
065 * read position of the input stream is positioned to the next certificate in
066 * the file:<p>
067 *
068 * <pre>
069 * FileInputStream fis = new FileInputStream(filename);
070 * BufferedInputStream bis = new BufferedInputStream(fis);
071 *
072 * CertificateFactory cf = CertificateFactory.getInstance("X.509");
073 *
074 * while (bis.available() > 0) {
075 * Certificate cert = cf.generateCertificate(bis);
076 * System.out.println(cert.toString());
077 * }
078 * </pre>
079 *
080 * <p>The following example parses a PKCS#7-formatted certificate reply stored
081 * in a file and extracts all the certificates from it:<p>
082 *
083 * <pre>
084 * FileInputStream fis = new FileInputStream(filename);
085 * CertificateFactory cf = CertificateFactory.getInstance("X.509");
086 * Collection c = cf.generateCertificates(fis);
087 * Iterator i = c.iterator();
088 * while (i.hasNext()) {
089 * Certificate cert = (Certificate)i.next();
090 * System.out.println(cert);
091 * }
092 * </pre>
093 *
094 * @author Hemma Prafullchandra
095 * @author Jan Luehe
096 * @author Sean Mullan
097 *
098 * @version 1.38, 05/05/07
099 *
100 * @see Certificate
101 * @see X509Certificate
102 * @see CertPath
103 * @see CRL
104 * @see X509CRL
105 *
106 * @since 1.2
107 */
108
109 public class CertificateFactory {
110
111 // The certificate type
112 private String type;
113
114 // The provider
115 private Provider provider;
116
117 // The provider implementation
118 private CertificateFactorySpi certFacSpi;
119
120 /**
121 * Creates a CertificateFactory object of the given type, and encapsulates
122 * the given provider implementation (SPI object) in it.
123 *
124 * @param certFacSpi the provider implementation.
125 * @param provider the provider.
126 * @param type the certificate type.
127 */
128 protected CertificateFactory(CertificateFactorySpi certFacSpi,
129 Provider provider, String type) {
130 this .certFacSpi = certFacSpi;
131 this .provider = provider;
132 this .type = type;
133 }
134
135 /**
136 * Returns a certificate factory object that implements the
137 * specified certificate type.
138 *
139 * <p> This method traverses the list of registered security Providers,
140 * starting with the most preferred Provider.
141 * A new CertificateFactory object encapsulating the
142 * CertificateFactorySpi implementation from the first
143 * Provider that supports the specified type is returned.
144 *
145 * <p> Note that the list of registered providers may be retrieved via
146 * the {@link Security#getProviders() Security.getProviders()} method.
147 *
148 * @param type the name of the requested certificate type.
149 * See Appendix A in the <a href=
150 * "../../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
151 * Java Cryptography Architecture API Specification & Reference </a>
152 * for information about standard certificate types.
153 *
154 * @return a certificate factory object for the specified type.
155 *
156 * @exception CertificateException if no Provider supports a
157 * CertificateFactorySpi implementation for the
158 * specified type.
159 *
160 * @see java.security.Provider
161 */
162 public static final CertificateFactory getInstance(String type)
163 throws CertificateException {
164 try {
165 Instance instance = GetInstance.getInstance(
166 "CertificateFactory", CertificateFactorySpi.class,
167 type);
168 return new CertificateFactory(
169 (CertificateFactorySpi) instance.impl,
170 instance.provider, type);
171 } catch (NoSuchAlgorithmException e) {
172 throw new CertificateException(type + " not found", e);
173 }
174 }
175
176 /**
177 * Returns a certificate factory object for the specified
178 * certificate type.
179 *
180 * <p> A new CertificateFactory object encapsulating the
181 * CertificateFactorySpi implementation from the specified provider
182 * is returned. The specified provider must be registered
183 * in the security provider list.
184 *
185 * <p> Note that the list of registered providers may be retrieved via
186 * the {@link Security#getProviders() Security.getProviders()} method.
187 *
188 * @param type the certificate type.
189 * See Appendix A in the <a href=
190 * "../../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
191 * Java Cryptography Architecture API Specification & Reference </a>
192 * for information about standard certificate types.
193 *
194 * @param provider the name of the provider.
195 *
196 * @return a certificate factory object for the specified type.
197 *
198 * @exception CertificateException if a CertificateFactorySpi
199 * implementation for the specified algorithm is not
200 * available from the specified provider.
201 *
202 * @exception NoSuchProviderException if the specified provider is not
203 * registered in the security provider list.
204 *
205 * @exception IllegalArgumentException if the provider name is null
206 * or empty.
207 *
208 * @see java.security.Provider
209 */
210 public static final CertificateFactory getInstance(String type,
211 String provider) throws CertificateException,
212 NoSuchProviderException {
213 try {
214 Instance instance = GetInstance.getInstance(
215 "CertificateFactory", CertificateFactorySpi.class,
216 type, provider);
217 return new CertificateFactory(
218 (CertificateFactorySpi) instance.impl,
219 instance.provider, type);
220 } catch (NoSuchAlgorithmException e) {
221 throw new CertificateException(type + " not found", e);
222 }
223 }
224
225 /**
226 * Returns a certificate factory object for the specified
227 * certificate type.
228 *
229 * <p> A new CertificateFactory object encapsulating the
230 * CertificateFactorySpi implementation from the specified Provider
231 * object is returned. Note that the specified Provider object
232 * does not have to be registered in the provider list.
233 *
234 * @param type the certificate type.
235 * See Appendix A in the <a href=
236 * "../../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
237 * Java Cryptography Architecture API Specification & Reference </a>
238 * for information about standard certificate types.
239
240 * @param provider the provider.
241 *
242 * @return a certificate factory object for the specified type.
243 *
244 * @exception CertificateException if a CertificateFactorySpi
245 * implementation for the specified algorithm is not available
246 * from the specified Provider object.
247 *
248 * @exception IllegalArgumentException if the <code>provider</code> is
249 * null.
250 *
251 * @see java.security.Provider
252 *
253 * @since 1.4
254 */
255 public static final CertificateFactory getInstance(String type,
256 Provider provider) throws CertificateException {
257 try {
258 Instance instance = GetInstance.getInstance(
259 "CertificateFactory", CertificateFactorySpi.class,
260 type, provider);
261 return new CertificateFactory(
262 (CertificateFactorySpi) instance.impl,
263 instance.provider, type);
264 } catch (NoSuchAlgorithmException e) {
265 throw new CertificateException(type + " not found", e);
266 }
267 }
268
269 /**
270 * Returns the provider of this certificate factory.
271 *
272 * @return the provider of this certificate factory.
273 */
274 public final Provider getProvider() {
275 return this .provider;
276 }
277
278 /**
279 * Returns the name of the certificate type associated with this
280 * certificate factory.
281 *
282 * @return the name of the certificate type associated with this
283 * certificate factory.
284 */
285 public final String getType() {
286 return this .type;
287 }
288
289 /**
290 * Generates a certificate object and initializes it with
291 * the data read from the input stream <code>inStream</code>.
292 *
293 * <p>In order to take advantage of the specialized certificate format
294 * supported by this certificate factory,
295 * the returned certificate object can be typecast to the corresponding
296 * certificate class. For example, if this certificate
297 * factory implements X.509 certificates, the returned certificate object
298 * can be typecast to the <code>X509Certificate</code> class.
299 *
300 * <p>In the case of a certificate factory for X.509 certificates, the
301 * certificate provided in <code>inStream</code> must be DER-encoded and
302 * may be supplied in binary or printable (Base64) encoding. If the
303 * certificate is provided in Base64 encoding, it must be bounded at
304 * the beginning by -----BEGIN CERTIFICATE-----, and must be bounded at
305 * the end by -----END CERTIFICATE-----.
306 *
307 * <p>Note that if the given input stream does not support
308 * {@link java.io.InputStream#mark(int) mark} and
309 * {@link java.io.InputStream#reset() reset}, this method will
310 * consume the entire input stream. Otherwise, each call to this
311 * method consumes one certificate and the read position of the
312 * input stream is positioned to the next available byte after
313 * the inherent end-of-certificate marker. If the data in the input stream
314 * does not contain an inherent end-of-certificate marker (other
315 * than EOF) and there is trailing data after the certificate is parsed, a
316 * <code>CertificateException</code> is thrown.
317 *
318 * @param inStream an input stream with the certificate data.
319 *
320 * @return a certificate object initialized with the data
321 * from the input stream.
322 *
323 * @exception CertificateException on parsing errors.
324 */
325 public final Certificate generateCertificate(InputStream inStream)
326 throws CertificateException {
327 return certFacSpi.engineGenerateCertificate(inStream);
328 }
329
330 /**
331 * Returns an iteration of the <code>CertPath</code> encodings supported
332 * by this certificate factory, with the default encoding first. See
333 * Appendix A in the
334 * <a href="../../../../technotes/guides/security/certpath/CertPathProgGuide.html#AppA">
335 * Java Certification Path API Programmer's Guide</a> for information about
336 * standard encoding names and their formats.
337 * <p>
338 * Attempts to modify the returned <code>Iterator</code> via its
339 * <code>remove</code> method result in an
340 * <code>UnsupportedOperationException</code>.
341 *
342 * @return an <code>Iterator</code> over the names of the supported
343 * <code>CertPath</code> encodings (as <code>String</code>s)
344 * @since 1.4
345 */
346 public final Iterator<String> getCertPathEncodings() {
347 return (certFacSpi.engineGetCertPathEncodings());
348 }
349
350 /**
351 * Generates a <code>CertPath</code> object and initializes it with
352 * the data read from the <code>InputStream</code> inStream. The data
353 * is assumed to be in the default encoding. The name of the default
354 * encoding is the first element of the <code>Iterator</code> returned by
355 * the {@link #getCertPathEncodings getCertPathEncodings} method.
356 *
357 * @param inStream an <code>InputStream</code> containing the data
358 * @return a <code>CertPath</code> initialized with the data from the
359 * <code>InputStream</code>
360 * @exception CertificateException if an exception occurs while decoding
361 * @since 1.4
362 */
363 public final CertPath generateCertPath(InputStream inStream)
364 throws CertificateException {
365 return (certFacSpi.engineGenerateCertPath(inStream));
366 }
367
368 /**
369 * Generates a <code>CertPath</code> object and initializes it with
370 * the data read from the <code>InputStream</code> inStream. The data
371 * is assumed to be in the specified encoding. See Appendix A in the
372 * <a href="../../../../technotes/guides/security/certpath/CertPathProgGuide.html#AppA">
373 * Java Certification Path API Programmer's Guide</a>
374 * for information about standard encoding names and their formats.
375 *
376 * @param inStream an <code>InputStream</code> containing the data
377 * @param encoding the encoding used for the data
378 * @return a <code>CertPath</code> initialized with the data from the
379 * <code>InputStream</code>
380 * @exception CertificateException if an exception occurs while decoding or
381 * the encoding requested is not supported
382 * @since 1.4
383 */
384 public final CertPath generateCertPath(InputStream inStream,
385 String encoding) throws CertificateException {
386 return (certFacSpi.engineGenerateCertPath(inStream, encoding));
387 }
388
389 /**
390 * Generates a <code>CertPath</code> object and initializes it with
391 * a <code>List</code> of <code>Certificate</code>s.
392 * <p>
393 * The certificates supplied must be of a type supported by the
394 * <code>CertificateFactory</code>. They will be copied out of the supplied
395 * <code>List</code> object.
396 *
397 * @param certificates a <code>List</code> of <code>Certificate</code>s
398 * @return a <code>CertPath</code> initialized with the supplied list of
399 * certificates
400 * @exception CertificateException if an exception occurs
401 * @since 1.4
402 */
403 public final CertPath generateCertPath(
404 List<? extends Certificate> certificates)
405 throws CertificateException {
406 return (certFacSpi.engineGenerateCertPath(certificates));
407 }
408
409 /**
410 * Returns a (possibly empty) collection view of the certificates read
411 * from the given input stream <code>inStream</code>.
412 *
413 * <p>In order to take advantage of the specialized certificate format
414 * supported by this certificate factory, each element in
415 * the returned collection view can be typecast to the corresponding
416 * certificate class. For example, if this certificate
417 * factory implements X.509 certificates, the elements in the returned
418 * collection can be typecast to the <code>X509Certificate</code> class.
419 *
420 * <p>In the case of a certificate factory for X.509 certificates,
421 * <code>inStream</code> may contain a sequence of DER-encoded certificates
422 * in the formats described for
423 * {@link #generateCertificate(java.io.InputStream) generateCertificate}.
424 * In addition, <code>inStream</code> may contain a PKCS#7 certificate
425 * chain. This is a PKCS#7 <i>SignedData</i> object, with the only
426 * significant field being <i>certificates</i>. In particular, the
427 * signature and the contents are ignored. This format allows multiple
428 * certificates to be downloaded at once. If no certificates are present,
429 * an empty collection is returned.
430 *
431 * <p>Note that if the given input stream does not support
432 * {@link java.io.InputStream#mark(int) mark} and
433 * {@link java.io.InputStream#reset() reset}, this method will
434 * consume the entire input stream.
435 *
436 * @param inStream the input stream with the certificates.
437 *
438 * @return a (possibly empty) collection view of
439 * java.security.cert.Certificate objects
440 * initialized with the data from the input stream.
441 *
442 * @exception CertificateException on parsing errors.
443 */
444 public final Collection<? extends Certificate> generateCertificates(
445 InputStream inStream) throws CertificateException {
446 return certFacSpi.engineGenerateCertificates(inStream);
447 }
448
449 /**
450 * Generates a certificate revocation list (CRL) object and initializes it
451 * with the data read from the input stream <code>inStream</code>.
452 *
453 * <p>In order to take advantage of the specialized CRL format
454 * supported by this certificate factory,
455 * the returned CRL object can be typecast to the corresponding
456 * CRL class. For example, if this certificate
457 * factory implements X.509 CRLs, the returned CRL object
458 * can be typecast to the <code>X509CRL</code> class.
459 *
460 * <p>Note that if the given input stream does not support
461 * {@link java.io.InputStream#mark(int) mark} and
462 * {@link java.io.InputStream#reset() reset}, this method will
463 * consume the entire input stream. Otherwise, each call to this
464 * method consumes one CRL and the read position of the input stream
465 * is positioned to the next available byte after the the inherent
466 * end-of-CRL marker. If the data in the
467 * input stream does not contain an inherent end-of-CRL marker (other
468 * than EOF) and there is trailing data after the CRL is parsed, a
469 * <code>CRLException</code> is thrown.
470 *
471 * @param inStream an input stream with the CRL data.
472 *
473 * @return a CRL object initialized with the data
474 * from the input stream.
475 *
476 * @exception CRLException on parsing errors.
477 */
478 public final CRL generateCRL(InputStream inStream)
479 throws CRLException {
480 return certFacSpi.engineGenerateCRL(inStream);
481 }
482
483 /**
484 * Returns a (possibly empty) collection view of the CRLs read
485 * from the given input stream <code>inStream</code>.
486 *
487 * <p>In order to take advantage of the specialized CRL format
488 * supported by this certificate factory, each element in
489 * the returned collection view can be typecast to the corresponding
490 * CRL class. For example, if this certificate
491 * factory implements X.509 CRLs, the elements in the returned
492 * collection can be typecast to the <code>X509CRL</code> class.
493 *
494 * <p>In the case of a certificate factory for X.509 CRLs,
495 * <code>inStream</code> may contain a sequence of DER-encoded CRLs.
496 * In addition, <code>inStream</code> may contain a PKCS#7 CRL
497 * set. This is a PKCS#7 <i>SignedData</i> object, with the only
498 * significant field being <i>crls</i>. In particular, the
499 * signature and the contents are ignored. This format allows multiple
500 * CRLs to be downloaded at once. If no CRLs are present,
501 * an empty collection is returned.
502 *
503 * <p>Note that if the given input stream does not support
504 * {@link java.io.InputStream#mark(int) mark} and
505 * {@link java.io.InputStream#reset() reset}, this method will
506 * consume the entire input stream.
507 *
508 * @param inStream the input stream with the CRLs.
509 *
510 * @return a (possibly empty) collection view of
511 * java.security.cert.CRL objects initialized with the data from the input
512 * stream.
513 *
514 * @exception CRLException on parsing errors.
515 */
516 public final Collection<? extends CRL> generateCRLs(
517 InputStream inStream) throws CRLException {
518 return certFacSpi.engineGenerateCRLs(inStream);
519 }
520 }
|