View Javadoc
1   /*
2    * Copyright (c) 1997, 2013, 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.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package java.security;
27  
28  import java.io.*;
29  import java.net.URI;
30  import java.security.cert.Certificate;
31  import java.security.cert.X509Certificate;
32  import java.security.cert.CertificateException;
33  import java.security.spec.AlgorithmParameterSpec;
34  import java.util.*;
35  import javax.crypto.SecretKey;
36  
37  import javax.security.auth.DestroyFailedException;
38  import javax.security.auth.callback.*;
39  
40  /**
41   * This class represents a storage facility for cryptographic
42   * keys and certificates.
43   *
44   * <p> A {@code KeyStore} manages different types of entries.
45   * Each type of entry implements the {@code KeyStore.Entry} interface.
46   * Three basic {@code KeyStore.Entry} implementations are provided:
47   *
48   * <ul>
49   * <li><b>KeyStore.PrivateKeyEntry</b>
50   * <p> This type of entry holds a cryptographic {@code PrivateKey},
51   * which is optionally stored in a protected format to prevent
52   * unauthorized access.  It is also accompanied by a certificate chain
53   * for the corresponding public key.
54   *
55   * <p> Private keys and certificate chains are used by a given entity for
56   * self-authentication. Applications for this authentication include software
57   * distribution organizations which sign JAR files as part of releasing
58   * and/or licensing software.
59   *
60   * <li><b>KeyStore.SecretKeyEntry</b>
61   * <p> This type of entry holds a cryptographic {@code SecretKey},
62   * which is optionally stored in a protected format to prevent
63   * unauthorized access.
64   *
65   * <li><b>KeyStore.TrustedCertificateEntry</b>
66   * <p> This type of entry contains a single public key {@code Certificate}
67   * belonging to another party. It is called a <i>trusted certificate</i>
68   * because the keystore owner trusts that the public key in the certificate
69   * indeed belongs to the identity identified by the <i>subject</i> (owner)
70   * of the certificate.
71   *
72   * <p>This type of entry can be used to authenticate other parties.
73   * </ul>
74   *
75   * <p> Each entry in a keystore is identified by an "alias" string. In the
76   * case of private keys and their associated certificate chains, these strings
77   * distinguish among the different ways in which the entity may authenticate
78   * itself. For example, the entity may authenticate itself using different
79   * certificate authorities, or using different public key algorithms.
80   *
81   * <p> Whether aliases are case sensitive is implementation dependent. In order
82   * to avoid problems, it is recommended not to use aliases in a KeyStore that
83   * only differ in case.
84   *
85   * <p> Whether keystores are persistent, and the mechanisms used by the
86   * keystore if it is persistent, are not specified here. This allows
87   * use of a variety of techniques for protecting sensitive (e.g., private or
88   * secret) keys. Smart cards or other integrated cryptographic engines
89   * (SafeKeyper) are one option, and simpler mechanisms such as files may also
90   * be used (in a variety of formats).
91   *
92   * <p> Typical ways to request a KeyStore object include
93   * relying on the default type and providing a specific keystore type.
94   *
95   * <ul>
96   * <li>To rely on the default type:
97   * <pre>
98   *    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
99   * </pre>
100  * The system will return a keystore implementation for the default type.
101  *
102  * <li>To provide a specific keystore type:
103  * <pre>
104  *      KeyStore ks = KeyStore.getInstance("JKS");
105  * </pre>
106  * The system will return the most preferred implementation of the
107  * specified keystore type available in the environment. <p>
108  * </ul>
109  *
110  * <p> Before a keystore can be accessed, it must be
111  * {@link #load(java.io.InputStream, char[]) loaded}.
112  * <pre>
113  *    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
114  *
115  *    // get user password and file input stream
116  *    char[] password = getPassword();
117  *
118  *    try (FileInputStream fis = new FileInputStream("keyStoreName")) {
119  *        ks.load(fis, password);
120  *    }
121  * </pre>
122  *
123  * To create an empty keystore using the above {@code load} method,
124  * pass {@code null} as the {@code InputStream} argument.
125  *
126  * <p> Once the keystore has been loaded, it is possible
127  * to read existing entries from the keystore, or to write new entries
128  * into the keystore:
129  * <pre>
130  *    KeyStore.ProtectionParameter protParam =
131  *        new KeyStore.PasswordProtection(password);
132  *
133  *    // get my private key
134  *    KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
135  *        ks.getEntry("privateKeyAlias", protParam);
136  *    PrivateKey myPrivateKey = pkEntry.getPrivateKey();
137  *
138  *    // save my secret key
139  *    javax.crypto.SecretKey mySecretKey;
140  *    KeyStore.SecretKeyEntry skEntry =
141  *        new KeyStore.SecretKeyEntry(mySecretKey);
142  *    ks.setEntry("secretKeyAlias", skEntry, protParam);
143  *
144  *    // store away the keystore
145  *    try (FileOutputStream fos = new FileOutputStream("newKeyStoreName")) {
146  *        ks.store(fos, password);
147  *    }
148  * </pre>
149  *
150  * Note that although the same password may be used to
151  * load the keystore, to protect the private key entry,
152  * to protect the secret key entry, and to store the keystore
153  * (as is shown in the sample code above),
154  * different passwords or other protection parameters
155  * may also be used.
156  *
157  * <p> Every implementation of the Java platform is required to support
158  * the following standard {@code KeyStore} type:
159  * <ul>
160  * <li>{@code PKCS12}</li>
161  * </ul>
162  * This type is described in the <a href=
163  * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore">
164  * KeyStore section</a> of the
165  * Java Cryptography Architecture Standard Algorithm Name Documentation.
166  * Consult the release documentation for your implementation to see if any
167  * other types are supported.
168  *
169  * @author Jan Luehe
170  *
171  * @see java.security.PrivateKey
172  * @see javax.crypto.SecretKey
173  * @see java.security.cert.Certificate
174  *
175  * @since 1.2
176  */
177 
178 public class KeyStore {
179 
180     /*
181      * Constant to lookup in the Security properties file to determine
182      * the default keystore type.
183      * In the Security properties file, the default keystore type is given as:
184      * <pre>
185      * keystore.type=jks
186      * </pre>
187      */
188     private static final String KEYSTORE_TYPE = "keystore.type";
189 
190     // The keystore type
191     private String type;
192 
193     // The provider
194     private Provider provider;
195 
196     // The provider implementation
197     private KeyStoreSpi keyStoreSpi;
198 
199     // Has this keystore been initialized (loaded)?
200     private boolean initialized = false;
201 
202     /**
203      * A marker interface for {@code KeyStore}
204      * {@link #load(KeyStore.LoadStoreParameter) load}
205      * and
206      * {@link #store(KeyStore.LoadStoreParameter) store}
207      * parameters.
208      *
209      * @since 1.5
210      */
211     public static interface LoadStoreParameter {
212         /**
213          * Gets the parameter used to protect keystore data.
214          *
215          * @return the parameter used to protect keystore data, or null
216          */
217         public ProtectionParameter getProtectionParameter();
218     }
219 
220     /**
221      * A marker interface for keystore protection parameters.
222      *
223      * <p> The information stored in a {@code ProtectionParameter}
224      * object protects the contents of a keystore.
225      * For example, protection parameters may be used to check
226      * the integrity of keystore data, or to protect the
227      * confidentiality of sensitive keystore data
228      * (such as a {@code PrivateKey}).
229      *
230      * @since 1.5
231      */
232     public static interface ProtectionParameter { }
233 
234     /**
235      * A password-based implementation of {@code ProtectionParameter}.
236      *
237      * @since 1.5
238      */
239     public static class PasswordProtection implements
240                 ProtectionParameter, javax.security.auth.Destroyable {
241 
242         private final char[] password;
243         private final String protectionAlgorithm;
244         private final AlgorithmParameterSpec protectionParameters;
245         private volatile boolean destroyed = false;
246 
247         /**
248          * Creates a password parameter.
249          *
250          * <p> The specified {@code password} is cloned before it is stored
251          * in the new {@code PasswordProtection} object.
252          *
253          * @param password the password, which may be {@code null}
254          */
255         public PasswordProtection(char[] password) {
256             this.password = (password == null) ? null : password.clone();
257             this.protectionAlgorithm = null;
258             this.protectionParameters = null;
259         }
260 
261         /**
262          * Creates a password parameter and specifies the protection algorithm
263          * and associated parameters to use when encrypting a keystore entry.
264          * <p>
265          * The specified {@code password} is cloned before it is stored in the
266          * new {@code PasswordProtection} object.
267          *
268          * @param password the password, which may be {@code null}
269          * @param protectionAlgorithm the encryption algorithm name, for
270          *     example, {@code PBEWithHmacSHA256AndAES_256}.
271          *     See the Cipher section in the <a href=
272          * "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher">
273          * Java Cryptography Architecture Standard Algorithm Name
274          * Documentation</a>
275          *     for information about standard encryption algorithm names.
276          * @param protectionParameters the encryption algorithm parameter
277          *     specification, which may be {@code null}
278          * @exception NullPointerException if {@code protectionAlgorithm} is
279          *     {@code null}
280          *
281          * @since 1.8
282          */
283         public PasswordProtection(char[] password, String protectionAlgorithm,
284             AlgorithmParameterSpec protectionParameters) {
285             if (protectionAlgorithm == null) {
286                 throw new NullPointerException("invalid null input");
287             }
288             this.password = (password == null) ? null : password.clone();
289             this.protectionAlgorithm = protectionAlgorithm;
290             this.protectionParameters = protectionParameters;
291         }
292 
293         /**
294          * Gets the name of the protection algorithm.
295          * If none was set then the keystore provider will use its default
296          * protection algorithm. The name of the default protection algorithm
297          * for a given keystore type is set using the
298          * {@code 'keystore.<type>.keyProtectionAlgorithm'} security property.
299          * For example, the
300          * {@code keystore.PKCS12.keyProtectionAlgorithm} property stores the
301          * name of the default key protection algorithm used for PKCS12
302          * keystores. If the security property is not set, an
303          * implementation-specific algorithm will be used.
304          *
305          * @return the algorithm name, or {@code null} if none was set
306          *
307          * @since 1.8
308          */
309         public String getProtectionAlgorithm() {
310             return protectionAlgorithm;
311         }
312 
313         /**
314          * Gets the parameters supplied for the protection algorithm.
315          *
316          * @return the algorithm parameter specification, or {@code  null},
317          *     if none was set
318          *
319          * @since 1.8
320          */
321         public AlgorithmParameterSpec getProtectionParameters() {
322             return protectionParameters;
323         }
324 
325         /**
326          * Gets the password.
327          *
328          * <p>Note that this method returns a reference to the password.
329          * If a clone of the array is created it is the caller's
330          * responsibility to zero out the password information
331          * after it is no longer needed.
332          *
333          * @see #destroy()
334          * @return the password, which may be {@code null}
335          * @exception IllegalStateException if the password has
336          *              been cleared (destroyed)
337          */
338         public synchronized char[] getPassword() {
339             if (destroyed) {
340                 throw new IllegalStateException("password has been cleared");
341             }
342             return password;
343         }
344 
345         /**
346          * Clears the password.
347          *
348          * @exception DestroyFailedException if this method was unable
349          *      to clear the password
350          */
351         public synchronized void destroy() throws DestroyFailedException {
352             destroyed = true;
353             if (password != null) {
354                 Arrays.fill(password, ' ');
355             }
356         }
357 
358         /**
359          * Determines if password has been cleared.
360          *
361          * @return true if the password has been cleared, false otherwise
362          */
363         public synchronized boolean isDestroyed() {
364             return destroyed;
365         }
366     }
367 
368     /**
369      * A ProtectionParameter encapsulating a CallbackHandler.
370      *
371      * @since 1.5
372      */
373     public static class CallbackHandlerProtection
374             implements ProtectionParameter {
375 
376         private final CallbackHandler handler;
377 
378         /**
379          * Constructs a new CallbackHandlerProtection from a
380          * CallbackHandler.
381          *
382          * @param handler the CallbackHandler
383          * @exception NullPointerException if handler is null
384          */
385         public CallbackHandlerProtection(CallbackHandler handler) {
386             if (handler == null) {
387                 throw new NullPointerException("handler must not be null");
388             }
389             this.handler = handler;
390         }
391 
392         /**
393          * Returns the CallbackHandler.
394          *
395          * @return the CallbackHandler.
396          */
397         public CallbackHandler getCallbackHandler() {
398             return handler;
399         }
400 
401     }
402 
403     /**
404      * A marker interface for {@code KeyStore} entry types.
405      *
406      * @since 1.5
407      */
408     public static interface Entry {
409 
410         /**
411          * Retrieves the attributes associated with an entry.
412          * <p>
413          * The default implementation returns an empty {@code Set}.
414          *
415          * @return an unmodifiable {@code Set} of attributes, possibly empty
416          *
417          * @since 1.8
418          */
419         public default Set<Attribute> getAttributes() {
420             return Collections.<Attribute>emptySet();
421         }
422 
423         /**
424          * An attribute associated with a keystore entry.
425          * It comprises a name and one or more values.
426          *
427          * @since 1.8
428          */
429         public interface Attribute {
430             /**
431              * Returns the attribute's name.
432              *
433              * @return the attribute name
434              */
435             public String getName();
436 
437             /**
438              * Returns the attribute's value.
439              * Multi-valued attributes encode their values as a single string.
440              *
441              * @return the attribute value
442              */
443             public String getValue();
444         }
445     }
446 
447     /**
448      * A {@code KeyStore} entry that holds a {@code PrivateKey}
449      * and corresponding certificate chain.
450      *
451      * @since 1.5
452      */
453     public static final class PrivateKeyEntry implements Entry {
454 
455         private final PrivateKey privKey;
456         private final Certificate[] chain;
457         private final Set<Attribute> attributes;
458 
459         /**
460          * Constructs a {@code PrivateKeyEntry} with a
461          * {@code PrivateKey} and corresponding certificate chain.
462          *
463          * <p> The specified {@code chain} is cloned before it is stored
464          * in the new {@code PrivateKeyEntry} object.
465          *
466          * @param privateKey the {@code PrivateKey}
467          * @param chain an array of {@code Certificate}s
468          *      representing the certificate chain.
469          *      The chain must be ordered and contain a
470          *      {@code Certificate} at index 0
471          *      corresponding to the private key.
472          *
473          * @exception NullPointerException if
474          *      {@code privateKey} or {@code chain}
475          *      is {@code null}
476          * @exception IllegalArgumentException if the specified chain has a
477          *      length of 0, if the specified chain does not contain
478          *      {@code Certificate}s of the same type,
479          *      or if the {@code PrivateKey} algorithm
480          *      does not match the algorithm of the {@code PublicKey}
481          *      in the end entity {@code Certificate} (at index 0)
482          */
483         public PrivateKeyEntry(PrivateKey privateKey, Certificate[] chain) {
484             this(privateKey, chain, Collections.<Attribute>emptySet());
485         }
486 
487         /**
488          * Constructs a {@code PrivateKeyEntry} with a {@code PrivateKey} and
489          * corresponding certificate chain and associated entry attributes.
490          *
491          * <p> The specified {@code chain} and {@code attributes} are cloned
492          * before they are stored in the new {@code PrivateKeyEntry} object.
493          *
494          * @param privateKey the {@code PrivateKey}
495          * @param chain an array of {@code Certificate}s
496          *      representing the certificate chain.
497          *      The chain must be ordered and contain a
498          *      {@code Certificate} at index 0
499          *      corresponding to the private key.
500          * @param attributes the attributes
501          *
502          * @exception NullPointerException if {@code privateKey}, {@code chain}
503          *      or {@code attributes} is {@code null}
504          * @exception IllegalArgumentException if the specified chain has a
505          *      length of 0, if the specified chain does not contain
506          *      {@code Certificate}s of the same type,
507          *      or if the {@code PrivateKey} algorithm
508          *      does not match the algorithm of the {@code PublicKey}
509          *      in the end entity {@code Certificate} (at index 0)
510          *
511          * @since 1.8
512          */
513         public PrivateKeyEntry(PrivateKey privateKey, Certificate[] chain,
514            Set<Attribute> attributes) {
515 
516             if (privateKey == null || chain == null || attributes == null) {
517                 throw new NullPointerException("invalid null input");
518             }
519             if (chain.length == 0) {
520                 throw new IllegalArgumentException
521                                 ("invalid zero-length input chain");
522             }
523 
524             Certificate[] clonedChain = chain.clone();
525             String certType = clonedChain[0].getType();
526             for (int i = 1; i < clonedChain.length; i++) {
527                 if (!certType.equals(clonedChain[i].getType())) {
528                     throw new IllegalArgumentException
529                                 ("chain does not contain certificates " +
530                                 "of the same type");
531                 }
532             }
533             if (!privateKey.getAlgorithm().equals
534                         (clonedChain[0].getPublicKey().getAlgorithm())) {
535                 throw new IllegalArgumentException
536                                 ("private key algorithm does not match " +
537                                 "algorithm of public key in end entity " +
538                                 "certificate (at index 0)");
539             }
540             this.privKey = privateKey;
541 
542             if (clonedChain[0] instanceof X509Certificate &&
543                 !(clonedChain instanceof X509Certificate[])) {
544 
545                 this.chain = new X509Certificate[clonedChain.length];
546                 System.arraycopy(clonedChain, 0,
547                                 this.chain, 0, clonedChain.length);
548             } else {
549                 this.chain = clonedChain;
550             }
551 
552             this.attributes =
553                 Collections.unmodifiableSet(new HashSet<>(attributes));
554         }
555 
556         /**
557          * Gets the {@code PrivateKey} from this entry.
558          *
559          * @return the {@code PrivateKey} from this entry
560          */
561         public PrivateKey getPrivateKey() {
562             return privKey;
563         }
564 
565         /**
566          * Gets the {@code Certificate} chain from this entry.
567          *
568          * <p> The stored chain is cloned before being returned.
569          *
570          * @return an array of {@code Certificate}s corresponding
571          *      to the certificate chain for the public key.
572          *      If the certificates are of type X.509,
573          *      the runtime type of the returned array is
574          *      {@code X509Certificate[]}.
575          */
576         public Certificate[] getCertificateChain() {
577             return chain.clone();
578         }
579 
580         /**
581          * Gets the end entity {@code Certificate}
582          * from the certificate chain in this entry.
583          *
584          * @return the end entity {@code Certificate} (at index 0)
585          *      from the certificate chain in this entry.
586          *      If the certificate is of type X.509,
587          *      the runtime type of the returned certificate is
588          *      {@code X509Certificate}.
589          */
590         public Certificate getCertificate() {
591             return chain[0];
592         }
593 
594         /**
595          * Retrieves the attributes associated with an entry.
596          * <p>
597          *
598          * @return an unmodifiable {@code Set} of attributes, possibly empty
599          *
600          * @since 1.8
601          */
602         @Override
603         public Set<Attribute> getAttributes() {
604             return attributes;
605         }
606 
607         /**
608          * Returns a string representation of this PrivateKeyEntry.
609          * @return a string representation of this PrivateKeyEntry.
610          */
611         public String toString() {
612             StringBuilder sb = new StringBuilder();
613             sb.append("Private key entry and certificate chain with "
614                 + chain.length + " elements:\r\n");
615             for (Certificate cert : chain) {
616                 sb.append(cert);
617                 sb.append("\r\n");
618             }
619             return sb.toString();
620         }
621 
622     }
623 
624     /**
625      * A {@code KeyStore} entry that holds a {@code SecretKey}.
626      *
627      * @since 1.5
628      */
629     public static final class SecretKeyEntry implements Entry {
630 
631         private final SecretKey sKey;
632         private final Set<Attribute> attributes;
633 
634         /**
635          * Constructs a {@code SecretKeyEntry} with a
636          * {@code SecretKey}.
637          *
638          * @param secretKey the {@code SecretKey}
639          *
640          * @exception NullPointerException if {@code secretKey}
641          *      is {@code null}
642          */
643         public SecretKeyEntry(SecretKey secretKey) {
644             if (secretKey == null) {
645                 throw new NullPointerException("invalid null input");
646             }
647             this.sKey = secretKey;
648             this.attributes = Collections.<Attribute>emptySet();
649         }
650 
651         /**
652          * Constructs a {@code SecretKeyEntry} with a {@code SecretKey} and
653          * associated entry attributes.
654          *
655          * <p> The specified {@code attributes} is cloned before it is stored
656          * in the new {@code SecretKeyEntry} object.
657          *
658          * @param secretKey the {@code SecretKey}
659          * @param attributes the attributes
660          *
661          * @exception NullPointerException if {@code secretKey} or
662          *     {@code attributes} is {@code null}
663          *
664          * @since 1.8
665          */
666         public SecretKeyEntry(SecretKey secretKey, Set<Attribute> attributes) {
667 
668             if (secretKey == null || attributes == null) {
669                 throw new NullPointerException("invalid null input");
670             }
671             this.sKey = secretKey;
672             this.attributes =
673                 Collections.unmodifiableSet(new HashSet<>(attributes));
674         }
675 
676         /**
677          * Gets the {@code SecretKey} from this entry.
678          *
679          * @return the {@code SecretKey} from this entry
680          */
681         public SecretKey getSecretKey() {
682             return sKey;
683         }
684 
685         /**
686          * Retrieves the attributes associated with an entry.
687          * <p>
688          *
689          * @return an unmodifiable {@code Set} of attributes, possibly empty
690          *
691          * @since 1.8
692          */
693         @Override
694         public Set<Attribute> getAttributes() {
695             return attributes;
696         }
697 
698         /**
699          * Returns a string representation of this SecretKeyEntry.
700          * @return a string representation of this SecretKeyEntry.
701          */
702         public String toString() {
703             return "Secret key entry with algorithm " + sKey.getAlgorithm();
704         }
705     }
706 
707     /**
708      * A {@code KeyStore} entry that holds a trusted
709      * {@code Certificate}.
710      *
711      * @since 1.5
712      */
713     public static final class TrustedCertificateEntry implements Entry {
714 
715         private final Certificate cert;
716         private final Set<Attribute> attributes;
717 
718         /**
719          * Constructs a {@code TrustedCertificateEntry} with a
720          * trusted {@code Certificate}.
721          *
722          * @param trustedCert the trusted {@code Certificate}
723          *
724          * @exception NullPointerException if
725          *      {@code trustedCert} is {@code null}
726          */
727         public TrustedCertificateEntry(Certificate trustedCert) {
728             if (trustedCert == null) {
729                 throw new NullPointerException("invalid null input");
730             }
731             this.cert = trustedCert;
732             this.attributes = Collections.<Attribute>emptySet();
733         }
734 
735         /**
736          * Constructs a {@code TrustedCertificateEntry} with a
737          * trusted {@code Certificate} and associated entry attributes.
738          *
739          * <p> The specified {@code attributes} is cloned before it is stored
740          * in the new {@code TrustedCertificateEntry} object.
741          *
742          * @param trustedCert the trusted {@code Certificate}
743          * @param attributes the attributes
744          *
745          * @exception NullPointerException if {@code trustedCert} or
746          *     {@code attributes} is {@code null}
747          *
748          * @since 1.8
749          */
750         public TrustedCertificateEntry(Certificate trustedCert,
751            Set<Attribute> attributes) {
752             if (trustedCert == null || attributes == null) {
753                 throw new NullPointerException("invalid null input");
754             }
755             this.cert = trustedCert;
756             this.attributes =
757                 Collections.unmodifiableSet(new HashSet<>(attributes));
758         }
759 
760         /**
761          * Gets the trusted {@code Certficate} from this entry.
762          *
763          * @return the trusted {@code Certificate} from this entry
764          */
765         public Certificate getTrustedCertificate() {
766             return cert;
767         }
768 
769         /**
770          * Retrieves the attributes associated with an entry.
771          * <p>
772          *
773          * @return an unmodifiable {@code Set} of attributes, possibly empty
774          *
775          * @since 1.8
776          */
777         @Override
778         public Set<Attribute> getAttributes() {
779             return attributes;
780         }
781 
782         /**
783          * Returns a string representation of this TrustedCertificateEntry.
784          * @return a string representation of this TrustedCertificateEntry.
785          */
786         public String toString() {
787             return "Trusted certificate entry:\r\n" + cert.toString();
788         }
789     }
790 
791     /**
792      * Creates a KeyStore object of the given type, and encapsulates the given
793      * provider implementation (SPI object) in it.
794      *
795      * @param keyStoreSpi the provider implementation.
796      * @param provider the provider.
797      * @param type the keystore type.
798      */
799     protected KeyStore(KeyStoreSpi keyStoreSpi, Provider provider, String type)
800     {
801         this.keyStoreSpi = keyStoreSpi;
802         this.provider = provider;
803         this.type = type;
804     }
805 
806     /**
807      * Returns a keystore object of the specified type.
808      *
809      * <p> This method traverses the list of registered security Providers,
810      * starting with the most preferred Provider.
811      * A new KeyStore object encapsulating the
812      * KeyStoreSpi implementation from the first
813      * Provider that supports the specified type is returned.
814      *
815      * <p> Note that the list of registered providers may be retrieved via
816      * the {@link Security#getProviders() Security.getProviders()} method.
817      *
818      * @param type the type of keystore.
819      * See the KeyStore section in the <a href=
820      * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore">
821      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
822      * for information about standard keystore types.
823      *
824      * @return a keystore object of the specified type.
825      *
826      * @exception KeyStoreException if no Provider supports a
827      *          KeyStoreSpi implementation for the
828      *          specified type.
829      *
830      * @see Provider
831      */
832     public static KeyStore getInstance(String type)
833         throws KeyStoreException
834     {
835         try {
836             Object[] objs = Security.getImpl(type, "KeyStore", (String)null);
837             return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);
838         } catch (NoSuchAlgorithmException nsae) {
839             throw new KeyStoreException(type + " not found", nsae);
840         } catch (NoSuchProviderException nspe) {
841             throw new KeyStoreException(type + " not found", nspe);
842         }
843     }
844 
845     /**
846      * Returns a keystore object of the specified type.
847      *
848      * <p> A new KeyStore object encapsulating the
849      * KeyStoreSpi implementation from the specified provider
850      * is returned.  The specified provider must be registered
851      * in the security provider list.
852      *
853      * <p> Note that the list of registered providers may be retrieved via
854      * the {@link Security#getProviders() Security.getProviders()} method.
855      *
856      * @param type the type of keystore.
857      * See the KeyStore section in the <a href=
858      * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore">
859      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
860      * for information about standard keystore types.
861      *
862      * @param provider the name of the provider.
863      *
864      * @return a keystore object of the specified type.
865      *
866      * @exception KeyStoreException if a KeyStoreSpi
867      *          implementation for the specified type is not
868      *          available from the specified provider.
869      *
870      * @exception NoSuchProviderException if the specified provider is not
871      *          registered in the security provider list.
872      *
873      * @exception IllegalArgumentException if the provider name is null
874      *          or empty.
875      *
876      * @see Provider
877      */
878     public static KeyStore getInstance(String type, String provider)
879         throws KeyStoreException, NoSuchProviderException
880     {
881         if (provider == null || provider.length() == 0)
882             throw new IllegalArgumentException("missing provider");
883         try {
884             Object[] objs = Security.getImpl(type, "KeyStore", provider);
885             return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);
886         } catch (NoSuchAlgorithmException nsae) {
887             throw new KeyStoreException(type + " not found", nsae);
888         }
889     }
890 
891     /**
892      * Returns a keystore object of the specified type.
893      *
894      * <p> A new KeyStore object encapsulating the
895      * KeyStoreSpi implementation from the specified Provider
896      * object is returned.  Note that the specified Provider object
897      * does not have to be registered in the provider list.
898      *
899      * @param type the type of keystore.
900      * See the KeyStore section in the <a href=
901      * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore">
902      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
903      * for information about standard keystore types.
904      *
905      * @param provider the provider.
906      *
907      * @return a keystore object of the specified type.
908      *
909      * @exception KeyStoreException if KeyStoreSpi
910      *          implementation for the specified type is not available
911      *          from the specified Provider object.
912      *
913      * @exception IllegalArgumentException if the specified provider is null.
914      *
915      * @see Provider
916      *
917      * @since 1.4
918      */
919     public static KeyStore getInstance(String type, Provider provider)
920         throws KeyStoreException
921     {
922         if (provider == null)
923             throw new IllegalArgumentException("missing provider");
924         try {
925             Object[] objs = Security.getImpl(type, "KeyStore", provider);
926             return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);
927         } catch (NoSuchAlgorithmException nsae) {
928             throw new KeyStoreException(type + " not found", nsae);
929         }
930     }
931 
932     /**
933      * Returns the default keystore type as specified by the
934      * {@code keystore.type} security property, or the string
935      * {@literal "jks"} (acronym for {@literal "Java keystore"})
936      * if no such property exists.
937      *
938      * <p>The default keystore type can be used by applications that do not
939      * want to use a hard-coded keystore type when calling one of the
940      * {@code getInstance} methods, and want to provide a default keystore
941      * type in case a user does not specify its own.
942      *
943      * <p>The default keystore type can be changed by setting the value of the
944      * {@code keystore.type} security property to the desired keystore type.
945      *
946      * @return the default keystore type as specified by the
947      * {@code keystore.type} security property, or the string {@literal "jks"}
948      * if no such property exists.
949      * @see java.security.Security security properties
950      */
951     public final static String getDefaultType() {
952         String kstype;
953         kstype = AccessController.doPrivileged(new PrivilegedAction<String>() {
954             public String run() {
955                 return Security.getProperty(KEYSTORE_TYPE);
956             }
957         });
958         if (kstype == null) {
959             kstype = "jks";
960         }
961         return kstype;
962     }
963 
964     /**
965      * Returns the provider of this keystore.
966      *
967      * @return the provider of this keystore.
968      */
969     public final Provider getProvider()
970     {
971         return this.provider;
972     }
973 
974     /**
975      * Returns the type of this keystore.
976      *
977      * @return the type of this keystore.
978      */
979     public final String getType()
980     {
981         return this.type;
982     }
983 
984     /**
985      * Returns the key associated with the given alias, using the given
986      * password to recover it.  The key must have been associated with
987      * the alias by a call to {@code setKeyEntry},
988      * or by a call to {@code setEntry} with a
989      * {@code PrivateKeyEntry} or {@code SecretKeyEntry}.
990      *
991      * @param alias the alias name
992      * @param password the password for recovering the key
993      *
994      * @return the requested key, or null if the given alias does not exist
995      * or does not identify a key-related entry.
996      *
997      * @exception KeyStoreException if the keystore has not been initialized
998      * (loaded).
999      * @exception NoSuchAlgorithmException if the algorithm for recovering the
1000      * key cannot be found
1001      * @exception UnrecoverableKeyException if the key cannot be recovered
1002      * (e.g., the given password is wrong).
1003      */
1004     public final Key getKey(String alias, char[] password)
1005         throws KeyStoreException, NoSuchAlgorithmException,
1006             UnrecoverableKeyException
1007     {
1008         if (!initialized) {
1009             throw new KeyStoreException("Uninitialized keystore");
1010         }
1011         return keyStoreSpi.engineGetKey(alias, password);
1012     }
1013 
1014     /**
1015      * Returns the certificate chain associated with the given alias.
1016      * The certificate chain must have been associated with the alias
1017      * by a call to {@code setKeyEntry},
1018      * or by a call to {@code setEntry} with a
1019      * {@code PrivateKeyEntry}.
1020      *
1021      * @param alias the alias name
1022      *
1023      * @return the certificate chain (ordered with the user's certificate first
1024      * followed by zero or more certificate authorities), or null if the given alias
1025      * does not exist or does not contain a certificate chain
1026      *
1027      * @exception KeyStoreException if the keystore has not been initialized
1028      * (loaded).
1029      */
1030     public final Certificate[] getCertificateChain(String alias)
1031         throws KeyStoreException
1032     {
1033         if (!initialized) {
1034             throw new KeyStoreException("Uninitialized keystore");
1035         }
1036         return keyStoreSpi.engineGetCertificateChain(alias);
1037     }
1038 
1039     /**
1040      * Returns the certificate associated with the given alias.
1041      *
1042      * <p> If the given alias name identifies an entry
1043      * created by a call to {@code setCertificateEntry},
1044      * or created by a call to {@code setEntry} with a
1045      * {@code TrustedCertificateEntry},
1046      * then the trusted certificate contained in that entry is returned.
1047      *
1048      * <p> If the given alias name identifies an entry
1049      * created by a call to {@code setKeyEntry},
1050      * or created by a call to {@code setEntry} with a
1051      * {@code PrivateKeyEntry},
1052      * then the first element of the certificate chain in that entry
1053      * is returned.
1054      *
1055      * @param alias the alias name
1056      *
1057      * @return the certificate, or null if the given alias does not exist or
1058      * does not contain a certificate.
1059      *
1060      * @exception KeyStoreException if the keystore has not been initialized
1061      * (loaded).
1062      */
1063     public final Certificate getCertificate(String alias)
1064         throws KeyStoreException
1065     {
1066         if (!initialized) {
1067             throw new KeyStoreException("Uninitialized keystore");
1068         }
1069         return keyStoreSpi.engineGetCertificate(alias);
1070     }
1071 
1072     /**
1073      * Returns the creation date of the entry identified by the given alias.
1074      *
1075      * @param alias the alias name
1076      *
1077      * @return the creation date of this entry, or null if the given alias does
1078      * not exist
1079      *
1080      * @exception KeyStoreException if the keystore has not been initialized
1081      * (loaded).
1082      */
1083     public final Date getCreationDate(String alias)
1084         throws KeyStoreException
1085     {
1086         if (!initialized) {
1087             throw new KeyStoreException("Uninitialized keystore");
1088         }
1089         return keyStoreSpi.engineGetCreationDate(alias);
1090     }
1091 
1092     /**
1093      * Assigns the given key to the given alias, protecting it with the given
1094      * password.
1095      *
1096      * <p>If the given key is of type {@code java.security.PrivateKey},
1097      * it must be accompanied by a certificate chain certifying the
1098      * corresponding public key.
1099      *
1100      * <p>If the given alias already exists, the keystore information
1101      * associated with it is overridden by the given key (and possibly
1102      * certificate chain).
1103      *
1104      * @param alias the alias name
1105      * @param key the key to be associated with the alias
1106      * @param password the password to protect the key
1107      * @param chain the certificate chain for the corresponding public
1108      * key (only required if the given key is of type
1109      * {@code java.security.PrivateKey}).
1110      *
1111      * @exception KeyStoreException if the keystore has not been initialized
1112      * (loaded), the given key cannot be protected, or this operation fails
1113      * for some other reason
1114      */
1115     public final void setKeyEntry(String alias, Key key, char[] password,
1116                                   Certificate[] chain)
1117         throws KeyStoreException
1118     {
1119         if (!initialized) {
1120             throw new KeyStoreException("Uninitialized keystore");
1121         }
1122         if ((key instanceof PrivateKey) &&
1123             (chain == null || chain.length == 0)) {
1124             throw new IllegalArgumentException("Private key must be "
1125                                                + "accompanied by certificate "
1126                                                + "chain");
1127         }
1128         keyStoreSpi.engineSetKeyEntry(alias, key, password, chain);
1129     }
1130 
1131     /**
1132      * Assigns the given key (that has already been protected) to the given
1133      * alias.
1134      *
1135      * <p>If the protected key is of type
1136      * {@code java.security.PrivateKey}, it must be accompanied by a
1137      * certificate chain certifying the corresponding public key. If the
1138      * underlying keystore implementation is of type {@code jks},
1139      * {@code key} must be encoded as an
1140      * {@code EncryptedPrivateKeyInfo} as defined in the PKCS #8 standard.
1141      *
1142      * <p>If the given alias already exists, the keystore information
1143      * associated with it is overridden by the given key (and possibly
1144      * certificate chain).
1145      *
1146      * @param alias the alias name
1147      * @param key the key (in protected format) to be associated with the alias
1148      * @param chain the certificate chain for the corresponding public
1149      *          key (only useful if the protected key is of type
1150      *          {@code java.security.PrivateKey}).
1151      *
1152      * @exception KeyStoreException if the keystore has not been initialized
1153      * (loaded), or if this operation fails for some other reason.
1154      */
1155     public final void setKeyEntry(String alias, byte[] key,
1156                                   Certificate[] chain)
1157         throws KeyStoreException
1158     {
1159         if (!initialized) {
1160             throw new KeyStoreException("Uninitialized keystore");
1161         }
1162         keyStoreSpi.engineSetKeyEntry(alias, key, chain);
1163     }
1164 
1165     /**
1166      * Assigns the given trusted certificate to the given alias.
1167      *
1168      * <p> If the given alias identifies an existing entry
1169      * created by a call to {@code setCertificateEntry},
1170      * or created by a call to {@code setEntry} with a
1171      * {@code TrustedCertificateEntry},
1172      * the trusted certificate in the existing entry
1173      * is overridden by the given certificate.
1174      *
1175      * @param alias the alias name
1176      * @param cert the certificate
1177      *
1178      * @exception KeyStoreException if the keystore has not been initialized,
1179      * or the given alias already exists and does not identify an
1180      * entry containing a trusted certificate,
1181      * or this operation fails for some other reason.
1182      */
1183     public final void setCertificateEntry(String alias, Certificate cert)
1184         throws KeyStoreException
1185     {
1186         if (!initialized) {
1187             throw new KeyStoreException("Uninitialized keystore");
1188         }
1189         keyStoreSpi.engineSetCertificateEntry(alias, cert);
1190     }
1191 
1192     /**
1193      * Deletes the entry identified by the given alias from this keystore.
1194      *
1195      * @param alias the alias name
1196      *
1197      * @exception KeyStoreException if the keystore has not been initialized,
1198      * or if the entry cannot be removed.
1199      */
1200     public final void deleteEntry(String alias)
1201         throws KeyStoreException
1202     {
1203         if (!initialized) {
1204             throw new KeyStoreException("Uninitialized keystore");
1205         }
1206         keyStoreSpi.engineDeleteEntry(alias);
1207     }
1208 
1209     /**
1210      * Lists all the alias names of this keystore.
1211      *
1212      * @return enumeration of the alias names
1213      *
1214      * @exception KeyStoreException if the keystore has not been initialized
1215      * (loaded).
1216      */
1217     public final Enumeration<String> aliases()
1218         throws KeyStoreException
1219     {
1220         if (!initialized) {
1221             throw new KeyStoreException("Uninitialized keystore");
1222         }
1223         return keyStoreSpi.engineAliases();
1224     }
1225 
1226     /**
1227      * Checks if the given alias exists in this keystore.
1228      *
1229      * @param alias the alias name
1230      *
1231      * @return true if the alias exists, false otherwise
1232      *
1233      * @exception KeyStoreException if the keystore has not been initialized
1234      * (loaded).
1235      */
1236     public final boolean containsAlias(String alias)
1237         throws KeyStoreException
1238     {
1239         if (!initialized) {
1240             throw new KeyStoreException("Uninitialized keystore");
1241         }
1242         return keyStoreSpi.engineContainsAlias(alias);
1243     }
1244 
1245     /**
1246      * Retrieves the number of entries in this keystore.
1247      *
1248      * @return the number of entries in this keystore
1249      *
1250      * @exception KeyStoreException if the keystore has not been initialized
1251      * (loaded).
1252      */
1253     public final int size()
1254         throws KeyStoreException
1255     {
1256         if (!initialized) {
1257             throw new KeyStoreException("Uninitialized keystore");
1258         }
1259         return keyStoreSpi.engineSize();
1260     }
1261 
1262     /**
1263      * Returns true if the entry identified by the given alias
1264      * was created by a call to {@code setKeyEntry},
1265      * or created by a call to {@code setEntry} with a
1266      * {@code PrivateKeyEntry} or a {@code SecretKeyEntry}.
1267      *
1268      * @param alias the alias for the keystore entry to be checked
1269      *
1270      * @return true if the entry identified by the given alias is a
1271      * key-related entry, false otherwise.
1272      *
1273      * @exception KeyStoreException if the keystore has not been initialized
1274      * (loaded).
1275      */
1276     public final boolean isKeyEntry(String alias)
1277         throws KeyStoreException
1278     {
1279         if (!initialized) {
1280             throw new KeyStoreException("Uninitialized keystore");
1281         }
1282         return keyStoreSpi.engineIsKeyEntry(alias);
1283     }
1284 
1285     /**
1286      * Returns true if the entry identified by the given alias
1287      * was created by a call to {@code setCertificateEntry},
1288      * or created by a call to {@code setEntry} with a
1289      * {@code TrustedCertificateEntry}.
1290      *
1291      * @param alias the alias for the keystore entry to be checked
1292      *
1293      * @return true if the entry identified by the given alias contains a
1294      * trusted certificate, false otherwise.
1295      *
1296      * @exception KeyStoreException if the keystore has not been initialized
1297      * (loaded).
1298      */
1299     public final boolean isCertificateEntry(String alias)
1300         throws KeyStoreException
1301     {
1302         if (!initialized) {
1303             throw new KeyStoreException("Uninitialized keystore");
1304         }
1305         return keyStoreSpi.engineIsCertificateEntry(alias);
1306     }
1307 
1308     /**
1309      * Returns the (alias) name of the first keystore entry whose certificate
1310      * matches the given certificate.
1311      *
1312      * <p> This method attempts to match the given certificate with each
1313      * keystore entry. If the entry being considered was
1314      * created by a call to {@code setCertificateEntry},
1315      * or created by a call to {@code setEntry} with a
1316      * {@code TrustedCertificateEntry},
1317      * then the given certificate is compared to that entry's certificate.
1318      *
1319      * <p> If the entry being considered was
1320      * created by a call to {@code setKeyEntry},
1321      * or created by a call to {@code setEntry} with a
1322      * {@code PrivateKeyEntry},
1323      * then the given certificate is compared to the first
1324      * element of that entry's certificate chain.
1325      *
1326      * @param cert the certificate to match with.
1327      *
1328      * @return the alias name of the first entry with a matching certificate,
1329      * or null if no such entry exists in this keystore.
1330      *
1331      * @exception KeyStoreException if the keystore has not been initialized
1332      * (loaded).
1333      */
1334     public final String getCertificateAlias(Certificate cert)
1335         throws KeyStoreException
1336     {
1337         if (!initialized) {
1338             throw new KeyStoreException("Uninitialized keystore");
1339         }
1340         return keyStoreSpi.engineGetCertificateAlias(cert);
1341     }
1342 
1343     /**
1344      * Stores this keystore to the given output stream, and protects its
1345      * integrity with the given password.
1346      *
1347      * @param stream the output stream to which this keystore is written.
1348      * @param password the password to generate the keystore integrity check
1349      *
1350      * @exception KeyStoreException if the keystore has not been initialized
1351      * (loaded).
1352      * @exception IOException if there was an I/O problem with data
1353      * @exception NoSuchAlgorithmException if the appropriate data integrity
1354      * algorithm could not be found
1355      * @exception CertificateException if any of the certificates included in
1356      * the keystore data could not be stored
1357      */
1358     public final void store(OutputStream stream, char[] password)
1359         throws KeyStoreException, IOException, NoSuchAlgorithmException,
1360             CertificateException
1361     {
1362         if (!initialized) {
1363             throw new KeyStoreException("Uninitialized keystore");
1364         }
1365         keyStoreSpi.engineStore(stream, password);
1366     }
1367 
1368     /**
1369      * Stores this keystore using the given {@code LoadStoreParameter}.
1370      *
1371      * @param param the {@code LoadStoreParameter}
1372      *          that specifies how to store the keystore,
1373      *          which may be {@code null}
1374      *
1375      * @exception IllegalArgumentException if the given
1376      *          {@code LoadStoreParameter}
1377      *          input is not recognized
1378      * @exception KeyStoreException if the keystore has not been initialized
1379      *          (loaded)
1380      * @exception IOException if there was an I/O problem with data
1381      * @exception NoSuchAlgorithmException if the appropriate data integrity
1382      *          algorithm could not be found
1383      * @exception CertificateException if any of the certificates included in
1384      *          the keystore data could not be stored
1385      *
1386      * @since 1.5
1387      */
1388     public final void store(LoadStoreParameter param)
1389                 throws KeyStoreException, IOException,
1390                 NoSuchAlgorithmException, CertificateException {
1391         if (!initialized) {
1392             throw new KeyStoreException("Uninitialized keystore");
1393         }
1394         keyStoreSpi.engineStore(param);
1395     }
1396 
1397     /**
1398      * Loads this KeyStore from the given input stream.
1399      *
1400      * <p>A password may be given to unlock the keystore
1401      * (e.g. the keystore resides on a hardware token device),
1402      * or to check the integrity of the keystore data.
1403      * If a password is not given for integrity checking,
1404      * then integrity checking is not performed.
1405      *
1406      * <p>In order to create an empty keystore, or if the keystore cannot
1407      * be initialized from a stream, pass {@code null}
1408      * as the {@code stream} argument.
1409      *
1410      * <p> Note that if this keystore has already been loaded, it is
1411      * reinitialized and loaded again from the given input stream.
1412      *
1413      * @param stream the input stream from which the keystore is loaded,
1414      * or {@code null}
1415      * @param password the password used to check the integrity of
1416      * the keystore, the password used to unlock the keystore,
1417      * or {@code null}
1418      *
1419      * @exception IOException if there is an I/O or format problem with the
1420      * keystore data, if a password is required but not given,
1421      * or if the given password was incorrect. If the error is due to a
1422      * wrong password, the {@link Throwable#getCause cause} of the
1423      * {@code IOException} should be an
1424      * {@code UnrecoverableKeyException}
1425      * @exception NoSuchAlgorithmException if the algorithm used to check
1426      * the integrity of the keystore cannot be found
1427      * @exception CertificateException if any of the certificates in the
1428      * keystore could not be loaded
1429      */
1430     public final void load(InputStream stream, char[] password)
1431         throws IOException, NoSuchAlgorithmException, CertificateException
1432     {
1433         keyStoreSpi.engineLoad(stream, password);
1434         initialized = true;
1435     }
1436 
1437     /**
1438      * Loads this keystore using the given {@code LoadStoreParameter}.
1439      *
1440      * <p> Note that if this KeyStore has already been loaded, it is
1441      * reinitialized and loaded again from the given parameter.
1442      *
1443      * @param param the {@code LoadStoreParameter}
1444      *          that specifies how to load the keystore,
1445      *          which may be {@code null}
1446      *
1447      * @exception IllegalArgumentException if the given
1448      *          {@code LoadStoreParameter}
1449      *          input is not recognized
1450      * @exception IOException if there is an I/O or format problem with the
1451      *          keystore data. If the error is due to an incorrect
1452      *         {@code ProtectionParameter} (e.g. wrong password)
1453      *         the {@link Throwable#getCause cause} of the
1454      *         {@code IOException} should be an
1455      *         {@code UnrecoverableKeyException}
1456      * @exception NoSuchAlgorithmException if the algorithm used to check
1457      *          the integrity of the keystore cannot be found
1458      * @exception CertificateException if any of the certificates in the
1459      *          keystore could not be loaded
1460      *
1461      * @since 1.5
1462      */
1463     public final void load(LoadStoreParameter param)
1464                 throws IOException, NoSuchAlgorithmException,
1465                 CertificateException {
1466 
1467         keyStoreSpi.engineLoad(param);
1468         initialized = true;
1469     }
1470 
1471     /**
1472      * Gets a keystore {@code Entry} for the specified alias
1473      * with the specified protection parameter.
1474      *
1475      * @param alias get the keystore {@code Entry} for this alias
1476      * @param protParam the {@code ProtectionParameter}
1477      *          used to protect the {@code Entry},
1478      *          which may be {@code null}
1479      *
1480      * @return the keystore {@code Entry} for the specified alias,
1481      *          or {@code null} if there is no such entry
1482      *
1483      * @exception NullPointerException if
1484      *          {@code alias} is {@code null}
1485      * @exception NoSuchAlgorithmException if the algorithm for recovering the
1486      *          entry cannot be found
1487      * @exception UnrecoverableEntryException if the specified
1488      *          {@code protParam} were insufficient or invalid
1489      * @exception UnrecoverableKeyException if the entry is a
1490      *          {@code PrivateKeyEntry} or {@code SecretKeyEntry}
1491      *          and the specified {@code protParam} does not contain
1492      *          the information needed to recover the key (e.g. wrong password)
1493      * @exception KeyStoreException if the keystore has not been initialized
1494      *          (loaded).
1495      * @see #setEntry(String, KeyStore.Entry, KeyStore.ProtectionParameter)
1496      *
1497      * @since 1.5
1498      */
1499     public final Entry getEntry(String alias, ProtectionParameter protParam)
1500                 throws NoSuchAlgorithmException, UnrecoverableEntryException,
1501                 KeyStoreException {
1502 
1503         if (alias == null) {
1504             throw new NullPointerException("invalid null input");
1505         }
1506         if (!initialized) {
1507             throw new KeyStoreException("Uninitialized keystore");
1508         }
1509         return keyStoreSpi.engineGetEntry(alias, protParam);
1510     }
1511 
1512     /**
1513      * Saves a keystore {@code Entry} under the specified alias.
1514      * The protection parameter is used to protect the
1515      * {@code Entry}.
1516      *
1517      * <p> If an entry already exists for the specified alias,
1518      * it is overridden.
1519      *
1520      * @param alias save the keystore {@code Entry} under this alias
1521      * @param entry the {@code Entry} to save
1522      * @param protParam the {@code ProtectionParameter}
1523      *          used to protect the {@code Entry},
1524      *          which may be {@code null}
1525      *
1526      * @exception NullPointerException if
1527      *          {@code alias} or {@code entry}
1528      *          is {@code null}
1529      * @exception KeyStoreException if the keystore has not been initialized
1530      *          (loaded), or if this operation fails for some other reason
1531      *
1532      * @see #getEntry(String, KeyStore.ProtectionParameter)
1533      *
1534      * @since 1.5
1535      */
1536     public final void setEntry(String alias, Entry entry,
1537                         ProtectionParameter protParam)
1538                 throws KeyStoreException {
1539         if (alias == null || entry == null) {
1540             throw new NullPointerException("invalid null input");
1541         }
1542         if (!initialized) {
1543             throw new KeyStoreException("Uninitialized keystore");
1544         }
1545         keyStoreSpi.engineSetEntry(alias, entry, protParam);
1546     }
1547 
1548     /**
1549      * Determines if the keystore {@code Entry} for the specified
1550      * {@code alias} is an instance or subclass of the specified
1551      * {@code entryClass}.
1552      *
1553      * @param alias the alias name
1554      * @param entryClass the entry class
1555      *
1556      * @return true if the keystore {@code Entry} for the specified
1557      *          {@code alias} is an instance or subclass of the
1558      *          specified {@code entryClass}, false otherwise
1559      *
1560      * @exception NullPointerException if
1561      *          {@code alias} or {@code entryClass}
1562      *          is {@code null}
1563      * @exception KeyStoreException if the keystore has not been
1564      *          initialized (loaded)
1565      *
1566      * @since 1.5
1567      */
1568     public final boolean
1569         entryInstanceOf(String alias,
1570                         Class<? extends KeyStore.Entry> entryClass)
1571         throws KeyStoreException
1572     {
1573 
1574         if (alias == null || entryClass == null) {
1575             throw new NullPointerException("invalid null input");
1576         }
1577         if (!initialized) {
1578             throw new KeyStoreException("Uninitialized keystore");
1579         }
1580         return keyStoreSpi.engineEntryInstanceOf(alias, entryClass);
1581     }
1582 
1583     /**
1584      * A description of a to-be-instantiated KeyStore object.
1585      *
1586      * <p>An instance of this class encapsulates the information needed to
1587      * instantiate and initialize a KeyStore object. That process is
1588      * triggered when the {@linkplain #getKeyStore} method is called.
1589      *
1590      * <p>This makes it possible to decouple configuration from KeyStore
1591      * object creation and e.g. delay a password prompt until it is
1592      * needed.
1593      *
1594      * @see KeyStore
1595      * @see javax.net.ssl.KeyStoreBuilderParameters
1596      * @since 1.5
1597      */
1598     public static abstract class Builder {
1599 
1600         // maximum times to try the callbackhandler if the password is wrong
1601         static final int MAX_CALLBACK_TRIES = 3;
1602 
1603         /**
1604          * Construct a new Builder.
1605          */
1606         protected Builder() {
1607             // empty
1608         }
1609 
1610         /**
1611          * Returns the KeyStore described by this object.
1612          *
1613          * @return the {@code KeyStore} described by this object
1614          * @exception KeyStoreException if an error occurred during the
1615          *   operation, for example if the KeyStore could not be
1616          *   instantiated or loaded
1617          */
1618         public abstract KeyStore getKeyStore() throws KeyStoreException;
1619 
1620         /**
1621          * Returns the ProtectionParameters that should be used to obtain
1622          * the {@link KeyStore.Entry Entry} with the given alias.
1623          * The {@code getKeyStore} method must be invoked before this
1624          * method may be called.
1625          *
1626          * @return the ProtectionParameters that should be used to obtain
1627          *   the {@link KeyStore.Entry Entry} with the given alias.
1628          * @param alias the alias of the KeyStore entry
1629          * @throws NullPointerException if alias is null
1630          * @throws KeyStoreException if an error occurred during the
1631          *   operation
1632          * @throws IllegalStateException if the getKeyStore method has
1633          *   not been invoked prior to calling this method
1634          */
1635         public abstract ProtectionParameter getProtectionParameter(String alias)
1636             throws KeyStoreException;
1637 
1638         /**
1639          * Returns a new Builder that encapsulates the given KeyStore.
1640          * The {@linkplain #getKeyStore} method of the returned object
1641          * will return {@code keyStore}, the {@linkplain
1642          * #getProtectionParameter getProtectionParameter()} method will
1643          * return {@code protectionParameters}.
1644          *
1645          * <p> This is useful if an existing KeyStore object needs to be
1646          * used with Builder-based APIs.
1647          *
1648          * @return a new Builder object
1649          * @param keyStore the KeyStore to be encapsulated
1650          * @param protectionParameter the ProtectionParameter used to
1651          *   protect the KeyStore entries
1652          * @throws NullPointerException if keyStore or
1653          *   protectionParameters is null
1654          * @throws IllegalArgumentException if the keyStore has not been
1655          *   initialized
1656          */
1657         public static Builder newInstance(final KeyStore keyStore,
1658                 final ProtectionParameter protectionParameter) {
1659             if ((keyStore == null) || (protectionParameter == null)) {
1660                 throw new NullPointerException();
1661             }
1662             if (keyStore.initialized == false) {
1663                 throw new IllegalArgumentException("KeyStore not initialized");
1664             }
1665             return new Builder() {
1666                 private volatile boolean getCalled;
1667 
1668                 public KeyStore getKeyStore() {
1669                     getCalled = true;
1670                     return keyStore;
1671                 }
1672 
1673                 public ProtectionParameter getProtectionParameter(String alias)
1674                 {
1675                     if (alias == null) {
1676                         throw new NullPointerException();
1677                     }
1678                     if (getCalled == false) {
1679                         throw new IllegalStateException
1680                             ("getKeyStore() must be called first");
1681                     }
1682                     return protectionParameter;
1683                 }
1684             };
1685         }
1686 
1687         /**
1688          * Returns a new Builder object.
1689          *
1690          * <p>The first call to the {@link #getKeyStore} method on the returned
1691          * builder will create a KeyStore of type {@code type} and call
1692          * its {@link KeyStore#load load()} method.
1693          * The {@code inputStream} argument is constructed from
1694          * {@code file}.
1695          * If {@code protection} is a
1696          * {@code PasswordProtection}, the password is obtained by
1697          * calling the {@code getPassword} method.
1698          * Otherwise, if {@code protection} is a
1699          * {@code CallbackHandlerProtection}, the password is obtained
1700          * by invoking the CallbackHandler.
1701          *
1702          * <p>Subsequent calls to {@link #getKeyStore} return the same object
1703          * as the initial call. If the initial call to failed with a
1704          * KeyStoreException, subsequent calls also throw a
1705          * KeyStoreException.
1706          *
1707          * <p>The KeyStore is instantiated from {@code provider} if
1708          * non-null. Otherwise, all installed providers are searched.
1709          *
1710          * <p>Calls to {@link #getProtectionParameter getProtectionParameter()}
1711          * will return a {@link KeyStore.PasswordProtection PasswordProtection}
1712          * object encapsulating the password that was used to invoke the
1713          * {@code load} method.
1714          *
1715          * <p><em>Note</em> that the {@link #getKeyStore} method is executed
1716          * within the {@link AccessControlContext} of the code invoking this
1717          * method.
1718          *
1719          * @return a new Builder object
1720          * @param type the type of KeyStore to be constructed
1721          * @param provider the provider from which the KeyStore is to
1722          *   be instantiated (or null)
1723          * @param file the File that contains the KeyStore data
1724          * @param protection the ProtectionParameter securing the KeyStore data
1725          * @throws NullPointerException if type, file or protection is null
1726          * @throws IllegalArgumentException if protection is not an instance
1727          *   of either PasswordProtection or CallbackHandlerProtection; or
1728          *   if file does not exist or does not refer to a normal file
1729          */
1730         public static Builder newInstance(String type, Provider provider,
1731                 File file, ProtectionParameter protection) {
1732             if ((type == null) || (file == null) || (protection == null)) {
1733                 throw new NullPointerException();
1734             }
1735             if ((protection instanceof PasswordProtection == false) &&
1736                 (protection instanceof CallbackHandlerProtection == false)) {
1737                 throw new IllegalArgumentException
1738                 ("Protection must be PasswordProtection or " +
1739                  "CallbackHandlerProtection");
1740             }
1741             if (file.isFile() == false) {
1742                 throw new IllegalArgumentException
1743                     ("File does not exist or it does not refer " +
1744                      "to a normal file: " + file);
1745             }
1746             return new FileBuilder(type, provider, file, protection,
1747                 AccessController.getContext());
1748         }
1749 
1750         private static final class FileBuilder extends Builder {
1751 
1752             private final String type;
1753             private final Provider provider;
1754             private final File file;
1755             private ProtectionParameter protection;
1756             private ProtectionParameter keyProtection;
1757             private final AccessControlContext context;
1758 
1759             private KeyStore keyStore;
1760 
1761             private Throwable oldException;
1762 
1763             FileBuilder(String type, Provider provider, File file,
1764                     ProtectionParameter protection,
1765                     AccessControlContext context) {
1766                 this.type = type;
1767                 this.provider = provider;
1768                 this.file = file;
1769                 this.protection = protection;
1770                 this.context = context;
1771             }
1772 
1773             public synchronized KeyStore getKeyStore() throws KeyStoreException
1774             {
1775                 if (keyStore != null) {
1776                     return keyStore;
1777                 }
1778                 if (oldException != null) {
1779                     throw new KeyStoreException
1780                         ("Previous KeyStore instantiation failed",
1781                          oldException);
1782                 }
1783                 PrivilegedExceptionAction<KeyStore> action =
1784                         new PrivilegedExceptionAction<KeyStore>() {
1785                     public KeyStore run() throws Exception {
1786                         if (protection instanceof CallbackHandlerProtection == false) {
1787                             return run0();
1788                         }
1789                         // when using a CallbackHandler,
1790                         // reprompt if the password is wrong
1791                         int tries = 0;
1792                         while (true) {
1793                             tries++;
1794                             try {
1795                                 return run0();
1796                             } catch (IOException e) {
1797                                 if ((tries < MAX_CALLBACK_TRIES)
1798                                         && (e.getCause() instanceof UnrecoverableKeyException)) {
1799                                     continue;
1800                                 }
1801                                 throw e;
1802                             }
1803                         }
1804                     }
1805                     public KeyStore run0() throws Exception {
1806                         KeyStore ks;
1807                         if (provider == null) {
1808                             ks = KeyStore.getInstance(type);
1809                         } else {
1810                             ks = KeyStore.getInstance(type, provider);
1811                         }
1812                         InputStream in = null;
1813                         char[] password = null;
1814                         try {
1815                             in = new FileInputStream(file);
1816                             if (protection instanceof PasswordProtection) {
1817                                 password =
1818                                 ((PasswordProtection)protection).getPassword();
1819                                 keyProtection = protection;
1820                             } else {
1821                                 CallbackHandler handler =
1822                                     ((CallbackHandlerProtection)protection)
1823                                     .getCallbackHandler();
1824                                 PasswordCallback callback = new PasswordCallback
1825                                     ("Password for keystore " + file.getName(),
1826                                     false);
1827                                 handler.handle(new Callback[] {callback});
1828                                 password = callback.getPassword();
1829                                 if (password == null) {
1830                                     throw new KeyStoreException("No password" +
1831                                                                 " provided");
1832                                 }
1833                                 callback.clearPassword();
1834                                 keyProtection = new PasswordProtection(password);
1835                             }
1836                             ks.load(in, password);
1837                             return ks;
1838                         } finally {
1839                             if (in != null) {
1840                                 in.close();
1841                             }
1842                         }
1843                     }
1844                 };
1845                 try {
1846                     keyStore = AccessController.doPrivileged(action, context);
1847                     return keyStore;
1848                 } catch (PrivilegedActionException e) {
1849                     oldException = e.getCause();
1850                     throw new KeyStoreException
1851                         ("KeyStore instantiation failed", oldException);
1852                 }
1853             }
1854 
1855             public synchronized ProtectionParameter
1856                         getProtectionParameter(String alias) {
1857                 if (alias == null) {
1858                     throw new NullPointerException();
1859                 }
1860                 if (keyStore == null) {
1861                     throw new IllegalStateException
1862                         ("getKeyStore() must be called first");
1863                 }
1864                 return keyProtection;
1865             }
1866         }
1867 
1868         /**
1869          * Returns a new Builder object.
1870          *
1871          * <p>Each call to the {@link #getKeyStore} method on the returned
1872          * builder will return a new KeyStore object of type {@code type}.
1873          * Its {@link KeyStore#load(KeyStore.LoadStoreParameter) load()}
1874          * method is invoked using a
1875          * {@code LoadStoreParameter} that encapsulates
1876          * {@code protection}.
1877          *
1878          * <p>The KeyStore is instantiated from {@code provider} if
1879          * non-null. Otherwise, all installed providers are searched.
1880          *
1881          * <p>Calls to {@link #getProtectionParameter getProtectionParameter()}
1882          * will return {@code protection}.
1883          *
1884          * <p><em>Note</em> that the {@link #getKeyStore} method is executed
1885          * within the {@link AccessControlContext} of the code invoking this
1886          * method.
1887          *
1888          * @return a new Builder object
1889          * @param type the type of KeyStore to be constructed
1890          * @param provider the provider from which the KeyStore is to
1891          *   be instantiated (or null)
1892          * @param protection the ProtectionParameter securing the Keystore
1893          * @throws NullPointerException if type or protection is null
1894          */
1895         public static Builder newInstance(final String type,
1896                 final Provider provider, final ProtectionParameter protection) {
1897             if ((type == null) || (protection == null)) {
1898                 throw new NullPointerException();
1899             }
1900             final AccessControlContext context = AccessController.getContext();
1901             return new Builder() {
1902                 private volatile boolean getCalled;
1903                 private IOException oldException;
1904 
1905                 private final PrivilegedExceptionAction<KeyStore> action
1906                         = new PrivilegedExceptionAction<KeyStore>() {
1907 
1908                     public KeyStore run() throws Exception {
1909                         KeyStore ks;
1910                         if (provider == null) {
1911                             ks = KeyStore.getInstance(type);
1912                         } else {
1913                             ks = KeyStore.getInstance(type, provider);
1914                         }
1915                         LoadStoreParameter param = new SimpleLoadStoreParameter(protection);
1916                         if (protection instanceof CallbackHandlerProtection == false) {
1917                             ks.load(param);
1918                         } else {
1919                             // when using a CallbackHandler,
1920                             // reprompt if the password is wrong
1921                             int tries = 0;
1922                             while (true) {
1923                                 tries++;
1924                                 try {
1925                                     ks.load(param);
1926                                     break;
1927                                 } catch (IOException e) {
1928                                     if (e.getCause() instanceof UnrecoverableKeyException) {
1929                                         if (tries < MAX_CALLBACK_TRIES) {
1930                                             continue;
1931                                         } else {
1932                                             oldException = e;
1933                                         }
1934                                     }
1935                                     throw e;
1936                                 }
1937                             }
1938                         }
1939                         getCalled = true;
1940                         return ks;
1941                     }
1942                 };
1943 
1944                 public synchronized KeyStore getKeyStore()
1945                         throws KeyStoreException {
1946                     if (oldException != null) {
1947                         throw new KeyStoreException
1948                             ("Previous KeyStore instantiation failed",
1949                              oldException);
1950                     }
1951                     try {
1952                         return AccessController.doPrivileged(action, context);
1953                     } catch (PrivilegedActionException e) {
1954                         Throwable cause = e.getCause();
1955                         throw new KeyStoreException
1956                             ("KeyStore instantiation failed", cause);
1957                     }
1958                 }
1959 
1960                 public ProtectionParameter getProtectionParameter(String alias)
1961                 {
1962                     if (alias == null) {
1963                         throw new NullPointerException();
1964                     }
1965                     if (getCalled == false) {
1966                         throw new IllegalStateException
1967                             ("getKeyStore() must be called first");
1968                     }
1969                     return protection;
1970                 }
1971             };
1972         }
1973 
1974     }
1975 
1976     static class SimpleLoadStoreParameter implements LoadStoreParameter {
1977 
1978         private final ProtectionParameter protection;
1979 
1980         SimpleLoadStoreParameter(ProtectionParameter protection) {
1981             this.protection = protection;
1982         }
1983 
1984         public ProtectionParameter getProtectionParameter() {
1985             return protection;
1986         }
1987     }
1988 
1989 }