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