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