001: /*
002: * @(#)KeyStore.java 1.37 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package java.security;
029:
030: import java.io.*;
031: import java.security.cert.Certificate;
032: import java.security.cert.CertificateException;
033: import java.util.*;
034:
035: /**
036: * This class represents an in-memory collection of keys and certificates.
037: * It manages two types of entries:
038: *
039: * <ul>
040: * <li><b>Key Entry</b>
041: * <p>This type of keystore entry holds very sensitive cryptographic key
042: * information, which is stored in a protected format to prevent unauthorized
043: * access.
044: *
045: * <p>Typically, a key stored in this type of entry is a secret key, or a
046: * private key accompanied by the certificate chain for the corresponding
047: * public key.
048: *
049: * <p>Private keys and certificate chains are used by a given entity for
050: * self-authentication. Applications for this authentication include software
051: * distribution organizations which sign JAR files as part of releasing
052: * and/or licensing software.<p>
053: *
054: * <li><b>Trusted Certificate Entry</b>
055: * <p>This type of entry contains a single public key certificate belonging to
056: * another party. It is called a <i>trusted certificate</i> because the
057: * keystore owner trusts that the public key in the certificate indeed belongs
058: * to the identity identified by the <i>subject</i> (owner) of the
059: * certificate.
060: *
061: * <p>This type of entry can be used to authenticate other parties.
062: * </ul>
063: *
064: * <p>Each entry in a keystore is identified by an "alias" string. In the
065: * case of private keys and their associated certificate chains, these strings
066: * distinguish among the different ways in which the entity may authenticate
067: * itself. For example, the entity may authenticate itself using different
068: * certificate authorities, or using different public key algorithms.
069: *
070: * <p>Whether keystores are persistent, and the mechanisms used by the
071: * keystore if it is persistent, are not specified here. This allows
072: * use of a variety of techniques for protecting sensitive (e.g., private or
073: * secret) keys. Smart cards or other integrated cryptographic engines
074: * (SafeKeyper) are one option, and simpler mechanisms such as files may also
075: * be used (in a variety of formats).
076: *
077: * <p>There are two ways to request a KeyStore object: by
078: * specifying either just a keystore type, or both a keystore type
079: * and a package provider.
080: *
081: * <ul>
082: * <li>If just a keystore type is specified:
083: * <pre>
084: * KeyStore ks = KeyStore.getInstance("JKS");
085: * </pre>
086: * the system will determine if there is an implementation of the keystore type
087: * requested available in the environment, and if there is more than one, if
088: * there is a preferred one.<p>
089: *
090: * <li>If both a keystore type and a package provider are specified:
091: * <pre>
092: * KeyStore ks = KeyStore.getInstance("JKS", "SUN");
093: * </pre>
094: * the system will determine if there is an implementation of the
095: * keystore type in the package requested, and throw an exception if there
096: * is not.
097: *
098: * </ul>
099: *
100: * <p>Before a keystore can be accessed, it must be
101: * {@link #load(java.io.InputStream, char[]) loaded}. In order to create
102: * an empty keystore, you pass <code>null</code>
103: * as the <code>InputStream</code> argument to the <code>load</code> method.
104: *
105: * @author Jan Luehe
106: *
107: * @version 1.29, 02/02/00
108: *
109: * @see java.security.PrivateKey
110: * @see java.security.cert.Certificate
111: *
112: * @since 1.2
113: */
114:
115: public class KeyStore {
116:
117: /*
118: * Constant to lookup in the Security properties file to determine
119: * the default keystore type.
120: * In the Security properties file, the default keystore type is given as:
121: * <pre>
122: * keystore.type=jks
123: * </pre>
124: */
125: private static final String KEYSTORE_TYPE = "keystore.type";
126:
127: // The keystore type
128: private String type;
129:
130: // The provider
131: private Provider provider;
132:
133: // The provider implementation
134: private KeyStoreSpi keyStoreSpi;
135:
136: // Has this keystore been initialized (loaded)?
137: private boolean initialized = false;
138:
139: /**
140: * Creates a KeyStore object of the given type, and encapsulates the given
141: * provider implementation (SPI object) in it.
142: *
143: * @param keyStoreSpi the provider implementation.
144: * @param provider the provider.
145: * @param type the keystore type.
146: */
147: protected KeyStore(KeyStoreSpi keyStoreSpi, Provider provider,
148: String type) {
149: this .keyStoreSpi = keyStoreSpi;
150: this .provider = provider;
151: this .type = type;
152: }
153:
154: /**
155: * Generates a keystore object of the given type.
156: *
157: * <p>If the default provider package provides a keystore implementation
158: * of the given type, an instance of <code>KeyStore</code> containing that
159: * implementation is returned. If the requested keystore type is not
160: * available in the default package, other packages are searched.
161: *
162: * @param type the type of keystore.
163: * See Appendix A in the <a href=
164: * "../../../guide/security/CryptoSpec.html#AppA">
165: * Java Cryptography Architecture API Specification & Reference </a>
166: * for information about standard keystore types.
167: *
168: * @return a keystore object of the specified type.
169: *
170: * @exception KeyStoreException if the requested keystore type is
171: * not available in the default provider package or any of the other
172: * provider packages that were searched.
173: */
174: public static KeyStore getInstance(String type)
175: throws KeyStoreException {
176: try {
177: Object[] objs = Security.getImpl(type, "KeyStore",
178: (String) null);
179: return new KeyStore((KeyStoreSpi) objs[0],
180: (Provider) objs[1], type);
181: } catch (NoSuchAlgorithmException nsae) {
182: throw new KeyStoreException(type + " not found");
183: } catch (NoSuchProviderException nspe) {
184: throw new KeyStoreException(type + " not found");
185: }
186: }
187:
188: /**
189: * Generates a keystore object for the specified keystore
190: * type from the specified provider.
191: *
192: * @param type the type of keystore.
193: * See Appendix A in the <a href=
194: * "../../../guide/security/CryptoSpec.html#AppA">
195: * Java Cryptography Architecture API Specification & Reference </a>
196: * for information about standard keystore types.
197: *
198: * @param provider the name of the provider.
199: *
200: * @return a keystore object of the specified type, as
201: * supplied by the specified provider.
202: *
203: * @exception KeyStoreException if the requested keystore type is not
204: * available from the provider.
205: *
206: * @exception NoSuchProviderException if the provider has not been
207: * configured.
208: *
209: * @exception IllegalArgumentException if the provider name is null
210: * or empty.
211: *
212: * @see Provider
213: */
214: public static KeyStore getInstance(String type, String provider)
215: throws KeyStoreException, NoSuchProviderException {
216: if (provider == null || provider.length() == 0)
217: throw new IllegalArgumentException("missing provider");
218: try {
219: Object[] objs = Security
220: .getImpl(type, "KeyStore", provider);
221: return new KeyStore((KeyStoreSpi) objs[0],
222: (Provider) objs[1], type);
223: } catch (NoSuchAlgorithmException nsae) {
224: throw new KeyStoreException(type + " not found");
225: }
226: }
227:
228: /**
229: * Generates a keystore object for the specified keystore
230: * type from the specified provider. Note: the <code>provider</code>
231: * doesn't have to be registered.
232: *
233: * @param type the type of keystore.
234: * See Appendix A in the <a href=
235: * "../../../guide/security/CryptoSpec.html#AppA">
236: * Java Cryptography Architecture API Specification & Reference </a>
237: * for information about standard keystore types.
238: *
239: * @param provider the provider.
240: *
241: * @return a keystore object of the specified type, as
242: * supplied by the specified provider.
243: *
244: * @exception KeyStoreException if the requested keystore type is not
245: * available from the provider.
246: *
247: * @exception IllegalArgumentException if the <code>provider</code> is
248: * null.
249: *
250: * @see Provider
251: *
252: * @since 1.4
253: */
254: public static KeyStore getInstance(String type, Provider provider)
255: throws KeyStoreException {
256: if (provider == null)
257: throw new IllegalArgumentException("missing provider");
258: try {
259: Object[] objs = Security
260: .getImpl(type, "KeyStore", provider);
261: return new KeyStore((KeyStoreSpi) objs[0],
262: (Provider) objs[1], type);
263: } catch (NoSuchAlgorithmException nsae) {
264: throw new KeyStoreException(type + " not found");
265: }
266: }
267:
268: /**
269: * Returns the provider of this keystore.
270: *
271: * @return the provider of this keystore.
272: */
273: public final Provider getProvider() {
274: return this .provider;
275: }
276:
277: /**
278: * Returns the type of this keystore.
279: *
280: * @return the type of this keystore.
281: */
282: public final String getType() {
283: return this .type;
284: }
285:
286: /**
287: * Returns the key associated with the given alias, using the given
288: * password to recover it.
289: *
290: * @param alias the alias name
291: * @param password the password for recovering the key
292: *
293: * @return the requested key, or null if the given alias does not exist
294: * or does not identify a <i>key entry</i>.
295: *
296: * @exception KeyStoreException if the keystore has not been initialized
297: * (loaded).
298: * @exception NoSuchAlgorithmException if the algorithm for recovering the
299: * key cannot be found
300: * @exception UnrecoverableKeyException if the key cannot be recovered
301: * (e.g., the given password is wrong).
302: */
303: public final Key getKey(String alias, char[] password)
304: throws KeyStoreException, NoSuchAlgorithmException,
305: UnrecoverableKeyException {
306: if (!initialized) {
307: throw new KeyStoreException("Uninitialized keystore");
308: }
309: return keyStoreSpi.engineGetKey(alias, password);
310: }
311:
312: /**
313: * Returns the certificate chain associated with the given alias.
314: *
315: * @param alias the alias name
316: *
317: * @return the certificate chain (ordered with the user's certificate first
318: * and the root certificate authority last), or null if the given alias
319: * does not exist or does not contain a certificate chain (i.e., the given
320: * alias identifies either a <i>trusted certificate entry</i> or a
321: * <i>key entry</i> without a certificate chain).
322: *
323: * @exception KeyStoreException if the keystore has not been initialized
324: * (loaded).
325: */
326: public final Certificate[] getCertificateChain(String alias)
327: throws KeyStoreException {
328: if (!initialized) {
329: throw new KeyStoreException("Uninitialized keystore");
330: }
331: return keyStoreSpi.engineGetCertificateChain(alias);
332: }
333:
334: /**
335: * Returns the certificate associated with the given alias.
336: *
337: * <p>If the given alias name identifies a
338: * <i>trusted certificate entry</i>, the certificate associated with that
339: * entry is returned. If the given alias name identifies a
340: * <i>key entry</i>, the first element of the certificate chain of that
341: * entry is returned, or null if that entry does not have a certificate
342: * chain.
343: *
344: * @param alias the alias name
345: *
346: * @return the certificate, or null if the given alias does not exist or
347: * does not contain a certificate.
348: *
349: * @exception KeyStoreException if the keystore has not been initialized
350: * (loaded).
351: */
352: public final Certificate getCertificate(String alias)
353: throws KeyStoreException {
354: if (!initialized) {
355: throw new KeyStoreException("Uninitialized keystore");
356: }
357: return keyStoreSpi.engineGetCertificate(alias);
358: }
359:
360: /**
361: * Returns the creation date of the entry identified by the given alias.
362: *
363: * @param alias the alias name
364: *
365: * @return the creation date of this entry, or null if the given alias does
366: * not exist
367: *
368: * @exception KeyStoreException if the keystore has not been initialized
369: * (loaded).
370: */
371: public final Date getCreationDate(String alias)
372: throws KeyStoreException {
373: if (!initialized) {
374: throw new KeyStoreException("Uninitialized keystore");
375: }
376: return keyStoreSpi.engineGetCreationDate(alias);
377: }
378:
379: /**
380: * Assigns the given key to the given alias, protecting it with the given
381: * password.
382: *
383: * <p>If the given key is of type <code>java.security.PrivateKey</code>,
384: * it must be accompanied by a certificate chain certifying the
385: * corresponding public key.
386: *
387: * <p>If the given alias already exists, the keystore information
388: * associated with it is overridden by the given key (and possibly
389: * certificate chain).
390: *
391: * @param alias the alias name
392: * @param key the key to be associated with the alias
393: * @param password the password to protect the key
394: * @param chain the certificate chain for the corresponding public
395: * key (only required if the given key is of type
396: * <code>java.security.PrivateKey</code>).
397: *
398: * @exception KeyStoreException if the keystore has not been initialized
399: * (loaded), the given key cannot be protected, or this operation fails
400: * for some other reason
401: */
402: public final void setKeyEntry(String alias, Key key,
403: char[] password, Certificate[] chain)
404: throws KeyStoreException {
405: if (!initialized) {
406: throw new KeyStoreException("Uninitialized keystore");
407: }
408: if ((key instanceof PrivateKey)
409: && (chain == null || chain.length == 0)) {
410: throw new IllegalArgumentException("Private key must be "
411: + "accompanied by certificate " + "chain");
412: }
413: keyStoreSpi.engineSetKeyEntry(alias, key, password, chain);
414: }
415:
416: /**
417: * Assigns the given key (that has already been protected) to the given
418: * alias.
419: *
420: * <p>If the protected key is of type
421: * <code>java.security.PrivateKey</code>, it must be accompanied by a
422: * certificate chain certifying the corresponding public key.
423: *
424: * <p>If the given alias already exists, the keystore information
425: * associated with it is overridden by the given key (and possibly
426: * certificate chain).
427: *
428: * @param alias the alias name
429: * @param key the key (in protected format) to be associated with the alias
430: * @param chain the certificate chain for the corresponding public
431: * key (only useful if the protected key is of type
432: * <code>java.security.PrivateKey</code>).
433: *
434: * @exception KeyStoreException if the keystore has not been initialized
435: * (loaded), or if this operation fails for some other reason.
436: */
437: public final void setKeyEntry(String alias, byte[] key,
438: Certificate[] chain) throws KeyStoreException {
439: if (!initialized) {
440: throw new KeyStoreException("Uninitialized keystore");
441: }
442: keyStoreSpi.engineSetKeyEntry(alias, key, chain);
443: }
444:
445: /**
446: * Assigns the given certificate to the given alias.
447: *
448: * <p>If the given alias already exists in this keystore and identifies a
449: * <i>trusted certificate entry</i>, the certificate associated with it is
450: * overridden by the given certificate.
451: *
452: * @param alias the alias name
453: * @param cert the certificate
454: *
455: * @exception KeyStoreException if the keystore has not been initialized,
456: * or the given alias already exists and does not identify a
457: * <i>trusted certificate entry</i>, or this operation fails for some
458: * other reason.
459: */
460: public final void setCertificateEntry(String alias, Certificate cert)
461: throws KeyStoreException {
462: if (!initialized) {
463: throw new KeyStoreException("Uninitialized keystore");
464: }
465: keyStoreSpi.engineSetCertificateEntry(alias, cert);
466: }
467:
468: /**
469: * Deletes the entry identified by the given alias from this keystore.
470: *
471: * @param alias the alias name
472: *
473: * @exception KeyStoreException if the keystore has not been initialized,
474: * or if the entry cannot be removed.
475: */
476: public final void deleteEntry(String alias)
477: throws KeyStoreException {
478: if (!initialized) {
479: throw new KeyStoreException("Uninitialized keystore");
480: }
481: keyStoreSpi.engineDeleteEntry(alias);
482: }
483:
484: /**
485: * Lists all the alias names of this keystore.
486: *
487: * @return enumeration of the alias names
488: *
489: * @exception KeyStoreException if the keystore has not been initialized
490: * (loaded).
491: */
492: public final Enumeration aliases() throws KeyStoreException {
493: if (!initialized) {
494: throw new KeyStoreException("Uninitialized keystore");
495: }
496: return keyStoreSpi.engineAliases();
497: }
498:
499: /**
500: * Checks if the given alias exists in this keystore.
501: *
502: * @param alias the alias name
503: *
504: * @return true if the alias exists, false otherwise
505: *
506: * @exception KeyStoreException if the keystore has not been initialized
507: * (loaded).
508: */
509: public final boolean containsAlias(String alias)
510: throws KeyStoreException {
511: if (!initialized) {
512: throw new KeyStoreException("Uninitialized keystore");
513: }
514: return keyStoreSpi.engineContainsAlias(alias);
515: }
516:
517: /**
518: * Retrieves the number of entries in this keystore.
519: *
520: * @return the number of entries in this keystore
521: *
522: * @exception KeyStoreException if the keystore has not been initialized
523: * (loaded).
524: */
525: public final int size() throws KeyStoreException {
526: if (!initialized) {
527: throw new KeyStoreException("Uninitialized keystore");
528: }
529: return keyStoreSpi.engineSize();
530: }
531:
532: /**
533: * Returns true if the entry identified by the given alias is a
534: * <i>key entry</i>, and false otherwise.
535: *
536: * @param alias the alias for the keystore entry to be checked
537: *
538: * @return true if the entry identified by the given alias is a
539: * <i>key entry</i>, false otherwise.
540: *
541: * @exception KeyStoreException if the keystore has not been initialized
542: * (loaded).
543: */
544: public final boolean isKeyEntry(String alias)
545: throws KeyStoreException {
546: if (!initialized) {
547: throw new KeyStoreException("Uninitialized keystore");
548: }
549: return keyStoreSpi.engineIsKeyEntry(alias);
550: }
551:
552: /**
553: * Returns true if the entry identified by the given alias is a
554: * <i>trusted certificate entry</i>, and false otherwise.
555: *
556: * @param alias the alias for the keystore entry to be checked
557: *
558: * @return true if the entry identified by the given alias is a
559: * <i>trusted certificate entry</i>, false otherwise.
560: *
561: * @exception KeyStoreException if the keystore has not been initialized
562: * (loaded).
563: */
564: public final boolean isCertificateEntry(String alias)
565: throws KeyStoreException {
566: if (!initialized) {
567: throw new KeyStoreException("Uninitialized keystore");
568: }
569: return keyStoreSpi.engineIsCertificateEntry(alias);
570: }
571:
572: /**
573: * Returns the (alias) name of the first keystore entry whose certificate
574: * matches the given certificate.
575: *
576: * <p>This method attempts to match the given certificate with each
577: * keystore entry. If the entry being considered
578: * is a <i>trusted certificate entry</i>, the given certificate is
579: * compared to that entry's certificate. If the entry being considered is
580: * a <i>key entry</i>, the given certificate is compared to the first
581: * element of that entry's certificate chain (if a chain exists).
582: *
583: * @param cert the certificate to match with.
584: *
585: * @return the (alias) name of the first entry with matching certificate,
586: * or null if no such entry exists in this keystore.
587: *
588: * @exception KeyStoreException if the keystore has not been initialized
589: * (loaded).
590: */
591: public final String getCertificateAlias(Certificate cert)
592: throws KeyStoreException {
593: if (!initialized) {
594: throw new KeyStoreException("Uninitialized keystore");
595: }
596: return keyStoreSpi.engineGetCertificateAlias(cert);
597: }
598:
599: /**
600: * Stores this keystore to the given output stream, and protects its
601: * integrity with the given password.
602: *
603: * @param stream the output stream to which this keystore is written.
604: * @param password the password to generate the keystore integrity check
605: *
606: * @exception KeyStoreException if the keystore has not been initialized
607: * (loaded).
608: * @exception IOException if there was an I/O problem with data
609: * @exception NoSuchAlgorithmException if the appropriate data integrity
610: * algorithm could not be found
611: * @exception CertificateException if any of the certificates included in
612: * the keystore data could not be stored
613: */
614: public final void store(OutputStream stream, char[] password)
615: throws KeyStoreException, IOException,
616: NoSuchAlgorithmException, CertificateException {
617: if (!initialized) {
618: throw new KeyStoreException("Uninitialized keystore");
619: }
620: keyStoreSpi.engineStore(stream, password);
621: }
622:
623: /**
624: * Loads this KeyStore from the given input stream.
625: *
626: * <p>If a password is given, it is used to check the integrity of the
627: * keystore data. Otherwise, the integrity of the keystore is not checked.
628: *
629: * <p>In order to create an empty keystore, or if the keystore cannot
630: * be initialized from a stream (e.g., because it is stored on a hardware
631: * token device), you pass <code>null</code>
632: * as the <code>stream</code> argument.
633: *
634: * <p> Note that if this KeyStore has already been loaded, it is
635: * reinitialized and loaded again from the given input stream.
636: *
637: * @param stream the input stream from which the keystore is loaded, or
638: * null if an empty keystore is to be created.
639: * @param password the (optional) password used to check the integrity of
640: * the keystore.
641: *
642: * @exception IOException if there is an I/O or format problem with the
643: * keystore data
644: * @exception NoSuchAlgorithmException if the algorithm used to check
645: * the integrity of the keystore cannot be found
646: * @exception CertificateException if any of the certificates in the
647: * keystore could not be loaded
648: */
649: public final void load(InputStream stream, char[] password)
650: throws IOException, NoSuchAlgorithmException,
651: CertificateException {
652: keyStoreSpi.engineLoad(stream, password);
653: initialized = true;
654: }
655:
656: /**
657: * Returns the default keystore type as specified in the Java security
658: * properties file, or the string "jks" (acronym for "Java keystore")
659: * if no such property exists.
660: * The Java security properties file is located in the file named
661: * <JAVA_HOME>/lib/security/java.security, where <JAVA_HOME>
662: * refers to the directory where the SDK was installed.
663: *
664: * <p>The default keystore type can be used by applications that do not
665: * want to use a hard-coded keystore type when calling one of the
666: * <code>getInstance</code> methods, and want to provide a default keystore
667: * type in case a user does not specify its own.
668: *
669: * <p>The default keystore type can be changed by setting the value of the
670: * "keystore.type" security property (in the Java security properties
671: * file) to the desired keystore type.
672: *
673: * @return the default keystore type as specified in the
674: * Java security properties file, or the string "jks"
675: * if no such property exists.
676: */
677: public final static String getDefaultType() {
678: String kstype;
679: kstype = (String) AccessController
680: .doPrivileged(new PrivilegedAction() {
681: public Object run() {
682: return Security.getProperty(KEYSTORE_TYPE);
683: }
684: });
685: if (kstype == null) {
686: kstype = "jks";
687: }
688: return kstype;
689: }
690: }
|