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