History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/security/KeyStore.java (1 of 18352 files). Show all

Unified · Split

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