KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > security > KeyStore


1 /*
2  * @(#)KeyStore.java 1.42 04/06/28
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.security;
9
10 import java.io.*;
11 import java.security.cert.Certificate JavaDoc;
12 import java.security.cert.X509Certificate JavaDoc;
13 import java.security.cert.CertificateException JavaDoc;
14 import java.util.*;
15 import javax.crypto.SecretKey;
16
17 import javax.security.auth.callback.*;
18
19 /**
20  * This class represents a storage facility for cryptographic
21  * keys and certificates.
22  *
23  * <p> A <code>KeyStore</code> manages different types of entries.
24  * Each type of entry implements the <code>KeyStore.Entry</code> interface.
25  * Three basic <code>KeyStore.Entry</code> implementations are provided:
26  *
27  * <ul>
28  * <li><b>KeyStore.PrivateKeyEntry</b>
29  * <p> This type of entry holds a cryptographic <code>PrivateKey</code>,
30  * which is optionally stored in a protected format to prevent
31  * unauthorized access. It is also accompanied by a certificate chain
32  * for the corresponding public key.
33  *
34  * <p> Private keys and certificate chains are used by a given entity for
35  * self-authentication. Applications for this authentication include software
36  * distribution organizations which sign JAR files as part of releasing
37  * and/or licensing software.
38  *
39  * <li><b>KeyStore.SecretKeyEntry</b>
40  * <p> This type of entry holds a cryptographic <code>SecretKey</code>,
41  * which is optionally stored in a protected format to prevent
42  * unauthorized access.
43  *
44  * <li><b>KeyStore.TrustedCertificateEntry</b>
45  * <p> This type of entry contains a single public key <code>Certificate</code>
46  * belonging to another party. It is called a <i>trusted certificate</i>
47  * because the keystore owner trusts that the public key in the certificate
48  * indeed belongs to the identity identified by the <i>subject</i> (owner)
49  * of the certificate.
50  *
51  * <p>This type of entry can be used to authenticate other parties.
52  * </ul>
53  *
54  * <p> Each entry in a keystore is identified by an "alias" string. In the
55  * case of private keys and their associated certificate chains, these strings
56  * distinguish among the different ways in which the entity may authenticate
57  * itself. For example, the entity may authenticate itself using different
58  * certificate authorities, or using different public key algorithms.
59  *
60  * <p> Whether keystores are persistent, and the mechanisms used by the
61  * keystore if it is persistent, are not specified here. This allows
62  * use of a variety of techniques for protecting sensitive (e.g., private or
63  * secret) keys. Smart cards or other integrated cryptographic engines
64  * (SafeKeyper) are one option, and simpler mechanisms such as files may also
65  * be used (in a variety of formats).
66  *
67  * <p> Typical ways to request a KeyStore object include
68  * relying on the default type and providing a specific keystore type.
69  *
70  * <ul>
71  * <li>To rely on the default type:
72  * <pre>
73  * KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
74  * </pre>
75  * The system will return a keystore implementation for the default type.
76  * <p>
77  *
78  * <li>To provide a specific keystore type:
79  * <pre>
80  * KeyStore ks = KeyStore.getInstance("JKS");
81  * </pre>
82  * The system will return the most preferred implementation of the
83  * specified keystore type available in the environment. <p>
84  * </ul>
85  *
86  * <p> Before a keystore can be accessed, it must be
87  * {@link #load(java.io.InputStream, char[]) loaded}.
88  * <pre>
89  * KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
90  *
91  * // get user password and file input stream
92  * char[] password = getPassword();
93  * java.io.FileInputStream fis =
94  * new java.io.FileInputStream("keyStoreName");
95  * ks.load(fis, password);
96  * fis.close();
97  * </pre>
98  *
99  * To create an empty keystore using the above <code>load</code> method,
100  * pass <code>null</code> as the <code>InputStream</code> argument.
101  *
102  * <p> Once the keystore has been loaded, it is possible
103  * to read existing entries from the keystore, or to write new entries
104  * into the keystore:
105  * <pre>
106  * // get my private key
107  * KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
108  * ks.getEntry("privateKeyAlias", password);
109  * PrivateKey myPrivateKey = pkEntry.getPrivateKey();
110  *
111  * // save my secret key
112  * javax.crypto.SecretKey mySecretKey;
113  * KeyStore.SecretKeyEntry skEntry =
114  * new KeyStore.SecretKeyEntry(mySecretKey);
115  * ks.setEntry("secretKeyAlias", skEntry, password);
116  *
117  * // store away the keystore
118  * java.io.FileOutputStream fos =
119  * new java.io.FileOutputStream("newKeyStoreName");
120  * ks.store(fos, password);
121  * fos.close();
122  * </pre>
123  *
124  * Note that although the same password may be used to
125  * load the keystore, to protect the private key entry,
126  * to protect the secret key entry, and to store the keystore
127  * (as is shown in the sample code above),
128  * different passwords or other protection parameters
129  * may also be used.
130  *
131  * @author Jan Luehe
132  *
133  * @version 1.42, 06/28/04
134  *
135  * @see java.security.PrivateKey
136  * @see javax.crypto.SecretKey
137  * @see java.security.cert.Certificate
138  *
139  * @since 1.2
140  */

141
142 public class KeyStore {
143
144     /*
145      * Constant to lookup in the Security properties file to determine
146      * the default keystore type.
147      * In the Security properties file, the default keystore type is given as:
148      * <pre>
149      * keystore.type=jks
150      * </pre>
151      */

152     private static final String JavaDoc KEYSTORE_TYPE = "keystore.type";
153
154     // The keystore type
155
private String JavaDoc type;
156
157     // The provider
158
private Provider JavaDoc provider;
159
160     // The provider implementation
161
private KeyStoreSpi JavaDoc keyStoreSpi;
162
163     // Has this keystore been initialized (loaded)?
164
private boolean initialized = false;
165
166     /**
167      * A marker interface for <code>KeyStore</code>
168      * {@link #load(KeyStore.LoadStoreParameter) load}
169      * and
170      * {@link #store(KeyStore.LoadStoreParameter) store}
171      * parameters.
172      *
173      * @since 1.5
174      */

175     public static interface LoadStoreParameter {
176     /**
177      * Gets the parameter used to protect keystore data.
178      *
179      * @return the parameter used to protect keystore data, or null
180      */

181     public ProtectionParameter getProtectionParameter();
182     }
183
184     /**
185      * A marker interface for keystore protection parameters.
186      *
187      * <p> The information stored in a <code>ProtectionParameter</code>
188      * object protects the contents of a keystore.
189      * For example, protection parameters may be used to check
190      * the integrity of keystore data, or to protect the
191      * confidentiality of sensitive keystore data
192      * (such as a <code>PrivateKey</code>).
193      *
194      * @since 1.5
195      */

196     public static interface ProtectionParameter { }
197
198     /**
199      * A password-based implementation of <code>ProtectionParameter</code>.
200      *
201      * @since 1.5
202      */

203     public static class PasswordProtection implements
204         ProtectionParameter, javax.security.auth.Destroyable JavaDoc {
205
206     private final char[] password;
207     private volatile boolean destroyed = false;
208
209     /**
210      * Creates a password parameter.
211      *
212      * <p> The specified <code>password</code> is cloned before it is stored
213      * in the new <code>PasswordProtection</code> object.
214      *
215      * @param password the password, which may be <code>null</code>
216      */

217     public PasswordProtection(char[] password) {
218         this.password = (password == null) ?
219                 null : (char[])password.clone();
220     }
221
222     /**
223      * Gets the password.
224      *
225      * <p>Note that this method returns a reference to the password.
226      * If a clone of the array is created it is the caller's
227      * responsibility to zero out the password information
228      * after it is no longer needed.
229      *
230      * @see #destroy()
231      * @return the password, which may be <code>null</code>
232      * @exception IllegalStateException if the password has
233      * been cleared (destroyed)
234      */

235     public synchronized char[] getPassword() {
236         if (destroyed) {
237         throw new IllegalStateException JavaDoc("password has been cleared");
238         }
239         return password;
240     }
241
242     /**
243      * Clears the password.
244      *
245      * @exception DestroyFailedException if this method was unable
246      * to clear the password
247      */

248     public synchronized void destroy()
249         throws javax.security.auth.DestroyFailedException JavaDoc {
250         destroyed = true;
251         if (password != null) {
252         Arrays.fill(password, ' ');
253         }
254     }
255
256     /**
257      * Determines if password has been cleared.
258      *
259      * @return true if the password has been cleared, false otherwise
260      */

261     public synchronized boolean isDestroyed() {
262         return destroyed;
263     }
264     }
265
266     /**
267      * A ProtectionParameter encapsulating a CallbackHandler.
268      *
269      * @since 1.5
270      */

271     public static class CallbackHandlerProtection
272         implements ProtectionParameter {
273         
274     private final CallbackHandler handler;
275     
276     /**
277      * Constructs a new CallbackHandlerProtection from a
278      * CallbackHandler.
279      *
280      * @param handler the CallbackHandler
281      * @exception NullPointerException if handler is null
282      */

283     public CallbackHandlerProtection(CallbackHandler handler) {
284         if (handler == null) {
285         throw new NullPointerException JavaDoc("handler must not be null");
286         }
287         this.handler = handler;
288     }
289     
290     /**
291      * Returns the CallbackHandler.
292      *
293      * @return the CallbackHandler.
294      */

295     public CallbackHandler getCallbackHandler() {
296         return handler;
297     }
298     
299     }
300
301     /**
302      * A marker interface for <code>KeyStore</code> entry types.
303      *
304      * @since 1.5
305      */

306     public static interface Entry { }
307
308     /**
309      * A <code>KeyStore</code> entry that holds a <code>PrivateKey</code>
310      * and corresponding certificate chain.
311      *
312      * @since 1.5
313      */

314     public static final class PrivateKeyEntry implements Entry {
315
316     private final PrivateKey JavaDoc privKey;
317     private final Certificate JavaDoc[] chain;
318
319     /**
320      * Constructs a <code>PrivateKeyEntry</code> with a
321      * <code>PrivateKey</code> and corresponding certificate chain.
322      *
323      * <p> The specified <code>chain</code> is cloned before it is stored
324      * in the new <code>PrivateKeyEntry</code> object.
325      *
326      * @param privateKey the <code>PrivateKey</code>
327      * @param chain an array of <code>Certificate</code>s
328      * representing the certificate chain.
329      * The chain must be ordered and contain a
330      * <code>Certificate</code> at index 0
331      * corresponding to the private key.
332      *
333      * @exception NullPointerException if
334      * <code>privateKey</code> or <code>chain</code>
335      * is <code>null</code>
336      * @exception IllegalArgumentException if the specified chain has a
337      * length of 0, if the specified chain does not contain
338      * <code>Certificate</code>s of the same type,
339      * or if the <code>PrivateKey</code> algorithm
340      * does not match the algorithm of the <code>PublicKey</code>
341      * in the end entity <code>Certificate</code> (at index 0)
342      */

343     public PrivateKeyEntry(PrivateKey JavaDoc privateKey, Certificate JavaDoc[] chain) {
344         if (privateKey == null || chain == null) {
345         throw new NullPointerException JavaDoc("invalid null input");
346         }
347         if (chain.length == 0) {
348         throw new IllegalArgumentException JavaDoc
349                 ("invalid zero-length input chain");
350         }
351
352         Certificate JavaDoc[] clonedChain = (Certificate JavaDoc[])chain.clone();
353         String JavaDoc certType = clonedChain[0].getType();
354         for (int i = 1; i < clonedChain.length; i++) {
355         if (!certType.equals(clonedChain[i].getType())) {
356             throw new IllegalArgumentException JavaDoc
357                 ("chain does not contain certificates " +
358                 "of the same type");
359         }
360         }
361         if (!privateKey.getAlgorithm().equals
362             (clonedChain[0].getPublicKey().getAlgorithm())) {
363         throw new IllegalArgumentException JavaDoc
364                 ("private key algorithm does not match " +
365                 "algorithm of public key in end entity " +
366                 "certificate (at index 0)");
367         }
368         this.privKey = privateKey;
369
370         if (clonedChain[0] instanceof X509Certificate JavaDoc &&
371         !(clonedChain instanceof X509Certificate JavaDoc[])) {
372
373         this.chain = new X509Certificate JavaDoc[clonedChain.length];
374         System.arraycopy(clonedChain, 0,
375                 this.chain, 0, clonedChain.length);
376         } else {
377         this.chain = clonedChain;
378         }
379     }
380
381     /**
382      * Gets the <code>PrivateKey</code> from this entry.
383      *
384      * @return the <code>PrivateKey</code> from this entry
385      */

386     public PrivateKey JavaDoc getPrivateKey() {
387         return privKey;
388     }
389
390     /**
391      * Gets the <code>Certificate</code> chain from this entry.
392      *
393      * <p> The stored chain is cloned before being returned.
394      *
395      * @return an array of <code>Certificate</code>s corresponding
396      * to the certificate chain for the public key.
397      * If the certificates are of type X.509,
398      * the runtime type of the returned array is
399      * <code>X509Certificate[]</code>.
400      */

401     public Certificate JavaDoc[] getCertificateChain() {
402         return (Certificate JavaDoc[])chain.clone();
403     }
404
405     /**
406      * Gets the end entity <code>Certificate</code>
407      * from the certificate chain in this entry.
408      *
409      * @return the end entity <code>Certificate</code> (at index 0)
410      * from the certificate chain in this entry.
411      * If the certificate is of type X.509,
412      * the runtime type of the returned certificate is
413      * <code>X509Certificate</code>.
414      */

415     public Certificate JavaDoc getCertificate() {
416         return chain[0];
417     }
418
419     /**
420      * Returns a string representation of this PrivateKeyEntry.
421      * @return a string representation of this PrivateKeyEntry.
422      */

423     public String JavaDoc toString() {
424         StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
425         sb.append("Private key entry and certificate chain with "
426         + chain.length + " elements:\r\n");
427         for (Certificate JavaDoc cert : chain) {
428         sb.append(cert);
429         sb.append("\r\n");
430         }
431         return sb.toString();
432     }
433
434     }
435
436     /**
437      * A <code>KeyStore</code> entry that holds a <code>SecretKey</code>.
438      *
439      * @since 1.5
440      */

441     public static final class SecretKeyEntry implements Entry {
442
443     private final SecretKey sKey;
444
445     /**
446      * Constructs a <code>SecretKeyEntry</code> with a
447      * <code>SecretKey</code>.
448      *
449      * @param secretKey the <code>SecretKey</code>
450      *
451      * @exception NullPointerException if <code>secretKey</code>
452      * is <code>null</code>
453      */

454     public SecretKeyEntry(SecretKey secretKey) {
455         if (secretKey == null) {
456         throw new NullPointerException JavaDoc("invalid null input");
457         }
458         this.sKey = secretKey;
459     }
460
461     /**
462      * Gets the <code>SecretKey</code> from this entry.
463      *
464      * @return the <code>SecretKey</code> from this entry
465      */

466     public SecretKey getSecretKey() {
467         return sKey;
468     }
469     
470     /**
471      * Returns a string representation of this SecretKeyEntry.
472      * @return a string representation of this SecretKeyEntry.
473      */

474     public String JavaDoc toString() {
475         return "Secret key entry with algorithm " + sKey.getAlgorithm();
476     }
477     }
478
479     /**
480      * A <code>KeyStore</code> entry that holds a trusted
481      * <code>Certificate</code>.
482      *
483      * @since 1.5
484      */

485     public static final class TrustedCertificateEntry implements Entry {
486
487     private final Certificate JavaDoc cert;
488
489     /**
490      * Constructs a <code>TrustedCertificateEntry</code> with a
491      * trusted <code>Certificate</code>.
492      *
493      * @param trustedCert the trusted <code>Certificate</code>
494      *
495      * @exception NullPointerException if
496      * <code>trustedCert</code> is <code>null</code>
497      */

498     public TrustedCertificateEntry(Certificate JavaDoc trustedCert) {
499         if (trustedCert == null) {
500         throw new NullPointerException JavaDoc("invalid null input");
501         }
502         this.cert = trustedCert;
503     }
504
505     /**
506      * Gets the trusted <code>Certficate</code> from this entry.
507      *
508      * @return the trusted <code>Certificate</code> from this entry
509      */

510     public Certificate JavaDoc getTrustedCertificate() {
511         return cert;
512     }
513     
514     /**
515      * Returns a string representation of this TrustedCertificateEntry.
516      * @return a string representation of this TrustedCertificateEntry.
517      */

518     public String JavaDoc toString() {
519         return "Trusted certificate entry:\r\n" + cert.toString();
520     }
521     }
522
523     /**
524      * Creates a KeyStore object of the given type, and encapsulates the given
525      * provider implementation (SPI object) in it.
526      *
527      * @param keyStoreSpi the provider implementation.
528      * @param provider the provider.
529      * @param type the keystore type.
530      */

531     protected KeyStore(KeyStoreSpi JavaDoc keyStoreSpi, Provider JavaDoc provider, String JavaDoc type)
532     {
533     this.keyStoreSpi = keyStoreSpi;
534     this.provider = provider;
535     this.type = type;
536     }
537
538     /**
539      * Generates a keystore object of the given type.
540      *
541      * <p>If the default provider package provides a keystore implementation
542      * of the given type, an instance of <code>KeyStore</code> containing that
543      * implementation is returned. If the requested keystore type is not
544      * available in the default package, other packages are searched.
545      *
546      * @param type the type of keystore.
547      * See Appendix A in the <a HREF=
548      * "../../../guide/security/CryptoSpec.html#AppA">
549      * Java Cryptography Architecture API Specification &amp; Reference </a>
550      * for information about standard keystore types.
551      *
552      * @return a keystore object of the specified type.
553      *
554      * @exception KeyStoreException if the requested keystore type is
555      * not available in the default provider package or any of the other
556      * provider packages that were searched.
557      */

558     public static KeyStore JavaDoc getInstance(String JavaDoc type)
559     throws KeyStoreException JavaDoc
560     {
561     try {
562         Object JavaDoc[] objs = Security.getImpl(type, "KeyStore", (String JavaDoc)null);
563         return new KeyStore JavaDoc((KeyStoreSpi JavaDoc)objs[0], (Provider JavaDoc)objs[1], type);
564     } catch (NoSuchAlgorithmException JavaDoc nsae) {
565         throw new KeyStoreException JavaDoc(type + " not found");
566     } catch (NoSuchProviderException JavaDoc nspe) {
567         throw new KeyStoreException JavaDoc(type + " not found");
568     }
569     }
570
571     /**
572      * Generates a keystore object for the specified keystore
573      * type from the specified provider.
574      *
575      * @param type the type of keystore.
576      * See Appendix A in the <a HREF=
577      * "../../../guide/security/CryptoSpec.html#AppA">
578      * Java Cryptography Architecture API Specification &amp; Reference </a>
579      * for information about standard keystore types.
580      *
581      * @param provider the name of the provider.
582      *
583      * @return a keystore object of the specified type, as
584      * supplied by the specified provider.
585      *
586      * @exception KeyStoreException if the requested keystore type is not
587      * available from the provider.
588      *
589      * @exception NoSuchProviderException if the provider has not been
590      * configured.
591      *
592      * @exception IllegalArgumentException if the provider name is null
593      * or empty.
594      *
595      * @see Provider
596      */

597     public static KeyStore JavaDoc getInstance(String JavaDoc type, String JavaDoc provider)
598     throws KeyStoreException JavaDoc, NoSuchProviderException JavaDoc
599     {
600     if (provider == null || provider.length() == 0)
601         throw new IllegalArgumentException JavaDoc("missing provider");
602     try {
603         Object JavaDoc[] objs = Security.getImpl(type, "KeyStore", provider);
604         return new KeyStore JavaDoc((KeyStoreSpi JavaDoc)objs[0], (Provider JavaDoc)objs[1], type);
605     } catch (NoSuchAlgorithmException JavaDoc nsae) {
606         throw new KeyStoreException JavaDoc(type + " not found");
607     }
608     }
609
610     /**
611      * Generates a keystore object for the specified keystore
612      * type from the specified provider. Note: the <code>provider</code>
613      * doesn't have to be registered.
614      *
615      * @param type the type of keystore.
616      * See Appendix A in the <a HREF=
617      * "../../../guide/security/CryptoSpec.html#AppA">
618      * Java Cryptography Architecture API Specification &amp; Reference </a>
619      * for information about standard keystore types.
620      *
621      * @param provider the provider.
622      *
623      * @return a keystore object of the specified type, as
624      * supplied by the specified provider.
625      *
626      * @exception KeyStoreException if the requested keystore type is not
627      * available from the provider.
628      *
629      * @exception IllegalArgumentException if the <code>provider</code> is
630      * null.
631      *
632      * @see Provider
633      *
634      * @since 1.4
635      */

636     public static KeyStore JavaDoc getInstance(String JavaDoc type, Provider JavaDoc provider)
637     throws KeyStoreException JavaDoc
638     {
639     if (provider == null)
640         throw new IllegalArgumentException JavaDoc("missing provider");
641     try {
642         Object JavaDoc[] objs = Security.getImpl(type, "KeyStore", provider);
643         return new KeyStore JavaDoc((KeyStoreSpi JavaDoc)objs[0], (Provider JavaDoc)objs[1], type);
644     } catch (NoSuchAlgorithmException JavaDoc nsae) {
645         throw new KeyStoreException JavaDoc(type + " not found");
646     }
647     }
648
649     /**
650      * Returns the default keystore type as specified in the Java security
651      * properties file, or the string
652      * &quot;jks&quot; (acronym for &quot;Java keystore&quot;)
653      * if no such property exists.
654      * The Java security properties file is located in the file named
655      * &lt;JAVA_HOME&gt;/lib/security/java.security, where &lt;JAVA_HOME&gt;
656      * refers to the directory where the JDK was installed.
657      *
658      * <p>The default keystore type can be used by applications that do not
659      * want to use a hard-coded keystore type when calling one of the
660      * <code>getInstance</code> methods, and want to provide a default keystore
661      * type in case a user does not specify its own.
662      *
663      * <p>The default keystore type can be changed by setting the value of the
664      * "keystore.type" security property (in the Java security properties
665      * file) to the desired keystore type.
666      *
667      * @return the default keystore type as specified in the
668      * Java security properties file, or the string &quot;jks&quot;
669      * if no such property exists.
670      */

671     public final static String JavaDoc getDefaultType() {
672     String JavaDoc kstype;
673     kstype = (String JavaDoc)AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
674         public Object JavaDoc run() {
675         return Security.getProperty(KEYSTORE_TYPE);
676         }
677     });
678     if (kstype == null) {
679         kstype = "jks";
680     }
681     return kstype;
682     }
683
684     /**
685      * Returns the provider of this keystore.
686      *
687      * @return the provider of this keystore.
688      */

689     public final Provider JavaDoc getProvider()
690     {
691     return this.provider;
692     }
693
694     /**
695      * Returns the type of this keystore.
696      *
697      * @return the type of this keystore.
698      */

699     public final String JavaDoc getType()
700     {
701     return this.type;
702     }
703
704     /**
705      * Returns the key associated with the given alias, using the given
706      * password to recover it. The key must have been associated with
707      * the alias by a call to <code>setKeyEntry</code>,
708      * or by a call to <code>setEntry</code> with a
709      * <code>PrivateKeyEntry</code> or <code>SecretKeyEntry</code>.
710      *
711      * @param alias the alias name
712      * @param password the password for recovering the key
713      *
714      * @return the requested key, or null if the given alias does not exist
715      * or does not identify a key-related entry.
716      *
717      * @exception KeyStoreException if the keystore has not been initialized
718      * (loaded).
719      * @exception NoSuchAlgorithmException if the algorithm for recovering the
720      * key cannot be found
721      * @exception UnrecoverableKeyException if the key cannot be recovered
722      * (e.g., the given password is wrong).
723      */

724     public final Key JavaDoc getKey(String JavaDoc alias, char[] password)
725     throws KeyStoreException JavaDoc, NoSuchAlgorithmException JavaDoc,
726         UnrecoverableKeyException JavaDoc
727     {
728     if (!initialized) {
729         throw new KeyStoreException JavaDoc("Uninitialized keystore");
730     }
731     return keyStoreSpi.engineGetKey(alias, password);
732     }
733
734     /**
735      * Returns the certificate chain associated with the given alias.
736      * The certificate chain must have been associated with the alias
737      * by a call to <code>setKeyEntry</code>,
738      * or by a call to <code>setEntry</code> with a
739      * <code>PrivateKeyEntry</code>.
740      *
741      * @param alias the alias name
742      *
743      * @return the certificate chain (ordered with the user's certificate first
744      * and the root certificate authority last), or null if the given alias
745      * does not exist or does not contain a certificate chain
746      *
747      * @exception KeyStoreException if the keystore has not been initialized
748      * (loaded).
749      */

750     public final Certificate JavaDoc[] getCertificateChain(String JavaDoc alias)
751     throws KeyStoreException JavaDoc
752     {
753     if (!initialized) {
754         throw new KeyStoreException JavaDoc("Uninitialized keystore");
755     }
756     return keyStoreSpi.engineGetCertificateChain(alias);
757     }
758
759     /**
760      * Returns the certificate associated with the given alias.
761      *
762      * <p> If the given alias name identifies an entry
763      * created by a call to <code>setCertificateEntry</code>,
764      * or created by a call to <code>setEntry</code> with a
765      * <code>TrustedCertificateEntry</code>,
766      * then the trusted certificate contained in that entry is returned.
767      *
768      * <p> If the given alias name identifies an entry
769      * created by a call to <code>setKeyEntry</code>,
770      * or created by a call to <code>setEntry</code> with a
771      * <code>PrivateKeyEntry</code>,
772      * then the first element of the certificate chain in that entry
773      * is returned.
774      *
775      * @param alias the alias name
776      *
777      * @return the certificate, or null if the given alias does not exist or
778      * does not contain a certificate.
779      *
780      * @exception KeyStoreException if the keystore has not been initialized
781      * (loaded).
782      */

783     public final Certificate JavaDoc getCertificate(String JavaDoc alias)
784     throws KeyStoreException JavaDoc
785     {
786     if (!initialized) {
787         throw new KeyStoreException JavaDoc("Uninitialized keystore");
788     }
789     return keyStoreSpi.engineGetCertificate(alias);
790     }
791
792     /**
793      * Returns the creation date of the entry identified by the given alias.
794      *
795      * @param alias the alias name
796      *
797      * @return the creation date of this entry, or null if the given alias does
798      * not exist
799      *
800      * @exception KeyStoreException if the keystore has not been initialized
801      * (loaded).
802      */

803     public final Date getCreationDate(String JavaDoc alias)
804     throws KeyStoreException JavaDoc
805     {
806     if (!initialized) {
807         throw new KeyStoreException JavaDoc("Uninitialized keystore");
808     }
809     return keyStoreSpi.engineGetCreationDate(alias);
810     }
811
812     /**
813      * Assigns the given key to the given alias, protecting it with the given
814      * password.
815      *
816      * <p>If the given key is of type <code>java.security.PrivateKey</code>,
817      * it must be accompanied by a certificate chain certifying the
818      * corresponding public key.
819      *
820      * <p>If the given alias already exists, the keystore information
821      * associated with it is overridden by the given key (and possibly
822      * certificate chain).
823      *
824      * @param alias the alias name
825      * @param key the key to be associated with the alias
826      * @param password the password to protect the key
827      * @param chain the certificate chain for the corresponding public
828      * key (only required if the given key is of type
829      * <code>java.security.PrivateKey</code>).
830      *
831      * @exception KeyStoreException if the keystore has not been initialized
832      * (loaded), the given key cannot be protected, or this operation fails
833      * for some other reason
834      */

835     public final void setKeyEntry(String JavaDoc alias, Key JavaDoc key, char[] password,
836                   Certificate JavaDoc[] chain)
837     throws KeyStoreException JavaDoc
838     {
839     if (!initialized) {
840         throw new KeyStoreException JavaDoc("Uninitialized keystore");
841     }
842     if ((key instanceof PrivateKey JavaDoc) &&
843         (chain == null || chain.length == 0)) {
844         throw new IllegalArgumentException JavaDoc("Private key must be "
845                            + "accompanied by certificate "
846                            + "chain");
847     }
848     keyStoreSpi.engineSetKeyEntry(alias, key, password, chain);
849     }
850
851     /**
852      * Assigns the given key (that has already been protected) to the given
853      * alias.
854      *
855      * <p>If the protected key is of type
856      * <code>java.security.PrivateKey</code>, it must be accompanied by a
857      * certificate chain certifying the corresponding public key. If the
858      * underlying keystore implementation is of type <code>jks</code>,
859      * <code>key</code> must be encoded as an
860      * <code>EncryptedPrivateKeyInfo</code> as defined in the PKCS #8 standard.
861      *
862      * <p>If the given alias already exists, the keystore information
863      * associated with it is overridden by the given key (and possibly
864      * certificate chain).
865      *
866      * @param alias the alias name
867      * @param key the key (in protected format) to be associated with the alias
868      * @param chain the certificate chain for the corresponding public
869      * key (only useful if the protected key is of type
870      * <code>java.security.PrivateKey</code>).
871      *
872      * @exception KeyStoreException if the keystore has not been initialized
873      * (loaded), or if this operation fails for some other reason.
874      */

875     public final void setKeyEntry(String JavaDoc alias, byte[] key,
876                   Certificate JavaDoc[] chain)
877     throws KeyStoreException JavaDoc
878     {
879     if (!initialized) {
880         throw new KeyStoreException JavaDoc("Uninitialized keystore");
881     }
882     keyStoreSpi.engineSetKeyEntry(alias, key, chain);
883     }
884
885     /**
886      * Assigns the given trusted certificate to the given alias.
887      *
888      * <p> If the given alias identifies an existing entry
889      * created by a call to <code>setCertificateEntry</code>,
890      * or created by a call to <code>setEntry</code> with a
891      * <code>TrustedCertificateEntry</code>,
892      * the trusted certificate in the existing entry
893      * is overridden by the given certificate.
894      *
895      * @param alias the alias name
896      * @param cert the certificate
897      *
898      * @exception KeyStoreException if the keystore has not been initialized,
899      * or the given alias already exists and does not identify an
900      * entry containing a trusted certificate,
901      * or this operation fails for some other reason.
902      */

903     public final void setCertificateEntry(String JavaDoc alias, Certificate JavaDoc cert)
904     throws KeyStoreException JavaDoc
905     {
906     if (!initialized) {
907         throw new KeyStoreException JavaDoc("Uninitialized keystore");
908     }
909     keyStoreSpi.engineSetCertificateEntry(alias, cert);
910     }
911
912     /**
913      * Deletes the entry identified by the given alias from this keystore.
914      *
915      * @param alias the alias name
916      *
917      * @exception KeyStoreException if the keystore has not been initialized,
918      * or if the entry cannot be removed.
919      */

920     public final void deleteEntry(String JavaDoc alias)
921     throws KeyStoreException JavaDoc
922     {
923     if (!initialized) {
924         throw new KeyStoreException JavaDoc("Uninitialized keystore");
925     }
926     keyStoreSpi.engineDeleteEntry(alias);
927     }
928
929     /**
930      * Lists all the alias names of this keystore.
931      *
932      * @return enumeration of the alias names
933      *
934      * @exception KeyStoreException if the keystore has not been initialized
935      * (loaded).
936      */

937     public final Enumeration<String JavaDoc> aliases()
938     throws KeyStoreException JavaDoc
939     {
940     if (!initialized) {
941         throw new KeyStoreException JavaDoc("Uninitialized keystore");
942     }
943     return keyStoreSpi.engineAliases();
944     }
945
946     /**
947      * Checks if the given alias exists in this keystore.
948      *
949      * @param alias the alias name
950      *
951      * @return true if the alias exists, false otherwise
952      *
953      * @exception KeyStoreException if the keystore has not been initialized
954      * (loaded).
955      */

956     public final boolean containsAlias(String