0001 /*
0002 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package java.security;
0027
0028 import java.io.*;
0029 import java.security.cert.Certificate;
0030 import java.security.cert.X509Certificate;
0031 import java.security.cert.CertificateException;
0032 import java.util.*;
0033 import javax.crypto.SecretKey;
0034
0035 import javax.security.auth.callback.*;
0036
0037 /**
0038 * This class represents a storage facility for cryptographic
0039 * keys and certificates.
0040 *
0041 * <p> A <code>KeyStore</code> manages different types of entries.
0042 * Each type of entry implements the <code>KeyStore.Entry</code> interface.
0043 * Three basic <code>KeyStore.Entry</code> implementations are provided:
0044 *
0045 * <ul>
0046 * <li><b>KeyStore.PrivateKeyEntry</b>
0047 * <p> This type of entry holds a cryptographic <code>PrivateKey</code>,
0048 * which is optionally stored in a protected format to prevent
0049 * unauthorized access. It is also accompanied by a certificate chain
0050 * for the corresponding public key.
0051 *
0052 * <p> Private keys and certificate chains are used by a given entity for
0053 * self-authentication. Applications for this authentication include software
0054 * distribution organizations which sign JAR files as part of releasing
0055 * and/or licensing software.
0056 *
0057 * <li><b>KeyStore.SecretKeyEntry</b>
0058 * <p> This type of entry holds a cryptographic <code>SecretKey</code>,
0059 * which is optionally stored in a protected format to prevent
0060 * unauthorized access.
0061 *
0062 * <li><b>KeyStore.TrustedCertificateEntry</b>
0063 * <p> This type of entry contains a single public key <code>Certificate</code>
0064 * belonging to another party. It is called a <i>trusted certificate</i>
0065 * because the keystore owner trusts that the public key in the certificate
0066 * indeed belongs to the identity identified by the <i>subject</i> (owner)
0067 * of the certificate.
0068 *
0069 * <p>This type of entry can be used to authenticate other parties.
0070 * </ul>
0071 *
0072 * <p> Each entry in a keystore is identified by an "alias" string. In the
0073 * case of private keys and their associated certificate chains, these strings
0074 * distinguish among the different ways in which the entity may authenticate
0075 * itself. For example, the entity may authenticate itself using different
0076 * certificate authorities, or using different public key algorithms.
0077 *
0078 * <p> Whether aliases are case sensitive is implementation dependent. In order
0079 * to avoid problems, it is recommended not to use aliases in a KeyStore that
0080 * only differ in case.
0081 *
0082 * <p> Whether keystores are persistent, and the mechanisms used by the
0083 * keystore if it is persistent, are not specified here. This allows
0084 * use of a variety of techniques for protecting sensitive (e.g., private or
0085 * secret) keys. Smart cards or other integrated cryptographic engines
0086 * (SafeKeyper) are one option, and simpler mechanisms such as files may also
0087 * be used (in a variety of formats).
0088 *
0089 * <p> Typical ways to request a KeyStore object include
0090 * relying on the default type and providing a specific keystore type.
0091 *
0092 * <ul>
0093 * <li>To rely on the default type:
0094 * <pre>
0095 * KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
0096 * </pre>
0097 * The system will return a keystore implementation for the default type.
0098 * <p>
0099 *
0100 * <li>To provide a specific keystore type:
0101 * <pre>
0102 * KeyStore ks = KeyStore.getInstance("JKS");
0103 * </pre>
0104 * The system will return the most preferred implementation of the
0105 * specified keystore type available in the environment. <p>
0106 * </ul>
0107 *
0108 * <p> Before a keystore can be accessed, it must be
0109 * {@link #load(java.io.InputStream, char[]) loaded}.
0110 * <pre>
0111 * KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
0112 *
0113 * // get user password and file input stream
0114 * char[] password = getPassword();
0115 *
0116 * java.io.FileInputStream fis = null;
0117 * try {
0118 * fis = new java.io.FileInputStream("keyStoreName");
0119 * ks.load(fis, password);
0120 * } finally {
0121 * if (fis != null) {
0122 * fis.close();
0123 * }
0124 * }
0125 * </pre>
0126 *
0127 * To create an empty keystore using the above <code>load</code> method,
0128 * pass <code>null</code> as the <code>InputStream</code> argument.
0129 *
0130 * <p> Once the keystore has been loaded, it is possible
0131 * to read existing entries from the keystore, or to write new entries
0132 * into the keystore:
0133 * <pre>
0134 * // get my private key
0135 * KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
0136 * ks.getEntry("privateKeyAlias", password);
0137 * PrivateKey myPrivateKey = pkEntry.getPrivateKey();
0138 *
0139 * // save my secret key
0140 * javax.crypto.SecretKey mySecretKey;
0141 * KeyStore.SecretKeyEntry skEntry =
0142 * new KeyStore.SecretKeyEntry(mySecretKey);
0143 * ks.setEntry("secretKeyAlias", skEntry,
0144 * new KeyStore.PasswordProtection(password));
0145 *
0146 * // store away the keystore
0147 * java.io.FileOutputStream fos = null;
0148 * try {
0149 * fos = new java.io.FileOutputStream("newKeyStoreName");
0150 * ks.store(fos, password);
0151 * } finally {
0152 * if (fos != null) {
0153 * fos.close();
0154 * }
0155 * }
0156 * </pre>
0157 *
0158 * Note that although the same password may be used to
0159 * load the keystore, to protect the private key entry,
0160 * to protect the secret key entry, and to store the keystore
0161 * (as is shown in the sample code above),
0162 * different passwords or other protection parameters
0163 * may also be used.
0164 *
0165 * @author Jan Luehe
0166 *
0167 * @version 1.61, 05/05/07
0168 *
0169 * @see java.security.PrivateKey
0170 * @see javax.crypto.SecretKey
0171 * @see java.security.cert.Certificate
0172 *
0173 * @since 1.2
0174 */
0175
0176 public class KeyStore {
0177
0178 /*
0179 * Constant to lookup in the Security properties file to determine
0180 * the default keystore type.
0181 * In the Security properties file, the default keystore type is given as:
0182 * <pre>
0183 * keystore.type=jks
0184 * </pre>
0185 */
0186 private static final String KEYSTORE_TYPE = "keystore.type";
0187
0188 // The keystore type
0189 private String type;
0190
0191 // The provider
0192 private Provider provider;
0193
0194 // The provider implementation
0195 private KeyStoreSpi keyStoreSpi;
0196
0197 // Has this keystore been initialized (loaded)?
0198 private boolean initialized = false;
0199
0200 /**
0201 * A marker interface for <code>KeyStore</code>
0202 * {@link #load(KeyStore.LoadStoreParameter) load}
0203 * and
0204 * {@link #store(KeyStore.LoadStoreParameter) store}
0205 * parameters.
0206 *
0207 * @since 1.5
0208 */
0209 public static interface LoadStoreParameter {
0210 /**
0211 * Gets the parameter used to protect keystore data.
0212 *
0213 * @return the parameter used to protect keystore data, or null
0214 */
0215 public ProtectionParameter getProtectionParameter();
0216 }
0217
0218 /**
0219 * A marker interface for keystore protection parameters.
0220 *
0221 * <p> The information stored in a <code>ProtectionParameter</code>
0222 * object protects the contents of a keystore.
0223 * For example, protection parameters may be used to check
0224 * the integrity of keystore data, or to protect the
0225 * confidentiality of sensitive keystore data
0226 * (such as a <code>PrivateKey</code>).
0227 *
0228 * @since 1.5
0229 */
0230 public static interface ProtectionParameter {
0231 }
0232
0233 /**
0234 * A password-based implementation of <code>ProtectionParameter</code>.
0235 *
0236 * @since 1.5
0237 */
0238 public static class PasswordProtection implements
0239 ProtectionParameter, javax.security.auth.Destroyable {
0240
0241 private final char[] password;
0242 private volatile boolean destroyed = false;
0243
0244 /**
0245 * Creates a password parameter.
0246 *
0247 * <p> The specified <code>password</code> is cloned before it is stored
0248 * in the new <code>PasswordProtection</code> object.
0249 *
0250 * @param password the password, which may be <code>null</code>
0251 */
0252 public PasswordProtection(char[] password) {
0253 this .password = (password == null) ? null
0254 : (char[]) password.clone();
0255 }
0256
0257 /**
0258 * Gets the password.
0259 *
0260 * <p>Note that this method returns a reference to the password.
0261 * If a clone of the array is created it is the caller's
0262 * responsibility to zero out the password information
0263 * after it is no longer needed.
0264 *
0265 * @see #destroy()
0266 * @return the password, which may be <code>null</code>
0267 * @exception IllegalStateException if the password has
0268 * been cleared (destroyed)
0269 */
0270 public synchronized char[] getPassword() {
0271 if (destroyed) {
0272 throw new IllegalStateException(
0273 "password has been cleared");
0274 }
0275 return password;
0276 }
0277
0278 /**
0279 * Clears the password.
0280 *
0281 * @exception DestroyFailedException if this method was unable
0282 * to clear the password
0283 */
0284 public synchronized void destroy()
0285 throws javax.security.auth.DestroyFailedException {
0286 destroyed = true;
0287 if (password != null) {
0288 Arrays.fill(password, ' ');
0289 }
0290 }
0291
0292 /**
0293 * Determines if password has been cleared.
0294 *
0295 * @return true if the password has been cleared, false otherwise
0296 */
0297 public synchronized boolean isDestroyed() {
0298 return destroyed;
0299 }
0300 }
0301
0302 /**
0303 * A ProtectionParameter encapsulating a CallbackHandler.
0304 *
0305 * @since 1.5
0306 */
0307 public static class CallbackHandlerProtection implements
0308 ProtectionParameter {
0309
0310 private final CallbackHandler handler;
0311
0312 /**
0313 * Constructs a new CallbackHandlerProtection from a
0314 * CallbackHandler.
0315 *
0316 * @param handler the CallbackHandler
0317 * @exception NullPointerException if handler is null
0318 */
0319 public CallbackHandlerProtection(CallbackHandler handler) {
0320 if (handler == null) {
0321 throw new NullPointerException(
0322 "handler must not be null");
0323 }
0324 this .handler = handler;
0325 }
0326
0327 /**
0328 * Returns the CallbackHandler.
0329 *
0330 * @return the CallbackHandler.
0331 */
0332 public CallbackHandler getCallbackHandler() {
0333 return handler;
0334 }
0335
0336 }
0337
0338 /**
0339 * A marker interface for <code>KeyStore</code> entry types.
0340 *
0341 * @since 1.5
0342 */
0343 public static interface Entry {
0344 }
0345
0346 /**
0347 * A <code>KeyStore</code> entry that holds a <code>PrivateKey</code>
0348 * and corresponding certificate chain.
0349 *
0350 * @since 1.5
0351 */
0352 public static final class PrivateKeyEntry implements Entry {
0353
0354 private final PrivateKey privKey;
0355 private final Certificate[] chain;
0356
0357 /**
0358 * Constructs a <code>PrivateKeyEntry</code> with a
0359 * <code>PrivateKey</code> and corresponding certificate chain.
0360 *
0361 * <p> The specified <code>chain</code> is cloned before it is stored
0362 * in the new <code>PrivateKeyEntry</code> object.
0363 *
0364 * @param privateKey the <code>PrivateKey</code>
0365 * @param chain an array of <code>Certificate</code>s
0366 * representing the certificate chain.
0367 * The chain must be ordered and contain a
0368 * <code>Certificate</code> at index 0
0369 * corresponding to the private key.
0370 *
0371 * @exception NullPointerException if
0372 * <code>privateKey</code> or <code>chain</code>
0373 * is <code>null</code>
0374 * @exception IllegalArgumentException if the specified chain has a
0375 * length of 0, if the specified chain does not contain
0376 * <code>Certificate</code>s of the same type,
0377 * or if the <code>PrivateKey</code> algorithm
0378 * does not match the algorithm of the <code>PublicKey</code>
0379 * in the end entity <code>Certificate</code> (at index 0)
0380 */
0381 public PrivateKeyEntry(PrivateKey privateKey,
0382 Certificate[] chain) {
0383 if (privateKey == null || chain == null) {
0384 throw new NullPointerException("invalid null input");
0385 }
0386 if (chain.length == 0) {
0387 throw new IllegalArgumentException(
0388 "invalid zero-length input chain");
0389 }
0390
0391 Certificate[] clonedChain = (Certificate[]) chain.clone();
0392 String certType = clonedChain[0].getType();
0393 for (int i = 1; i < clonedChain.length; i++) {
0394 if (!certType.equals(clonedChain[i].getType())) {
0395 throw new IllegalArgumentException(
0396 "chain does not contain certificates "
0397 + "of the same type");
0398 }
0399 }
0400 if (!privateKey.getAlgorithm().equals(
0401 clonedChain[0].getPublicKey().getAlgorithm())) {
0402 throw new IllegalArgumentException(
0403 "private key algorithm does not match "
0404 + "algorithm of public key in end entity "
0405 + "certificate (at index 0)");
0406 }
0407 this .privKey = privateKey;
0408
0409 if (clonedChain[0] instanceof X509Certificate
0410 && !(clonedChain instanceof X509Certificate[])) {
0411
0412 this .chain = new X509Certificate[clonedChain.length];
0413 System.arraycopy(clonedChain, 0, this .chain, 0,
0414 clonedChain.length);
0415 } else {
0416 this .chain = clonedChain;
0417 }
0418 }
0419
0420 /**
0421 * Gets the <code>PrivateKey</code> from this entry.
0422 *
0423 * @return the <code>PrivateKey</code> from this entry
0424 */
0425 public PrivateKey getPrivateKey() {
0426 return privKey;
0427 }
0428
0429 /**
0430 * Gets the <code>Certificate</code> chain from this entry.
0431 *
0432 * <p> The stored chain is cloned before being returned.
0433 *
0434 * @return an array of <code>Certificate</code>s corresponding
0435 * to the certificate chain for the public key.
0436 * If the certificates are of type X.509,
0437 * the runtime type of the returned array is
0438 * <code>X509Certificate[]</code>.
0439 */
0440 public Certificate[] getCertificateChain() {
0441 return (Certificate[]) chain.clone();
0442 }
0443
0444 /**
0445 * Gets the end entity <code>Certificate</code>
0446 * from the certificate chain in this entry.
0447 *
0448 * @return the end entity <code>Certificate</code> (at index 0)
0449 * from the certificate chain in this entry.
0450 * If the certificate is of type X.509,
0451 * the runtime type of the returned certificate is
0452 * <code>X509Certificate</code>.
0453 */
0454 public Certificate getCertificate() {
0455 return chain[0];
0456 }
0457
0458 /**
0459 * Returns a string representation of this PrivateKeyEntry.
0460 * @return a string representation of this PrivateKeyEntry.
0461 */
0462 public String toString() {
0463 StringBuilder sb = new StringBuilder();
0464 sb.append("Private key entry and certificate chain with "
0465 + chain.length + " elements:\r\n");
0466 for (Certificate cert : chain) {
0467 sb.append(cert);
0468 sb.append("\r\n");
0469 }
0470 return sb.toString();
0471 }
0472
0473 }
0474
0475 /**
0476 * A <code>KeyStore</code> entry that holds a <code>SecretKey</code>.
0477 *
0478 * @since 1.5
0479 */
0480 public static final class SecretKeyEntry implements Entry {
0481
0482 private final SecretKey sKey;
0483
0484 /**
0485 * Constructs a <code>SecretKeyEntry</code> with a
0486 * <code>SecretKey</code>.
0487 *
0488 * @param secretKey the <code>SecretKey</code>
0489 *
0490 * @exception NullPointerException if <code>secretKey</code>
0491 * is <code>null</code>
0492 */
0493 public SecretKeyEntry(SecretKey secretKey) {
0494 if (secretKey == null) {
0495 throw new NullPointerException("invalid null input");
0496 }
0497 this .sKey = secretKey;
0498 }
0499
0500 /**
0501 * Gets the <code>SecretKey</code> from this entry.
0502 *
0503 * @return the <code>SecretKey</code> from this entry
0504 */
0505 public SecretKey getSecretKey() {
0506 return sKey;
0507 }
0508
0509 /**
0510 * Returns a string representation of this SecretKeyEntry.
0511 * @return a string representation of this SecretKeyEntry.
0512 */
0513 public String toString() {
0514 return "Secret key entry with algorithm "
0515 + sKey.getAlgorithm();
0516 }
0517 }
0518
0519 /**
0520 * A <code>KeyStore</code> entry that holds a trusted
0521 * <code>Certificate</code>.
0522 *
0523 * @since 1.5
0524 */
0525 public static final class TrustedCertificateEntry implements Entry {
0526
0527 private final Certificate cert;
0528
0529 /**
0530 * Constructs a <code>TrustedCertificateEntry</code> with a
0531 * trusted <code>Certificate</code>.
0532 *
0533 * @param trustedCert the trusted <code>Certificate</code>
0534 *
0535 * @exception NullPointerException if
0536 * <code>trustedCert</code> is <code>null</code>
0537 */
0538 public TrustedCertificateEntry(Certificate trustedCert) {
0539 if (trustedCert == null) {
0540 throw new NullPointerException("invalid null input");
0541 }
0542 this .cert = trustedCert;
0543 }
0544
0545 /**
0546 * Gets the trusted <code>Certficate</code> from this entry.
0547 *
0548 * @return the trusted <code>Certificate</code> from this entry
0549 */
0550 public Certificate getTrustedCertificate() {
0551 return cert;
0552 }
0553
0554 /**
0555 * Returns a string representation of this TrustedCertificateEntry.
0556 * @return a string representation of this TrustedCertificateEntry.
0557 */
0558 public String toString() {
0559 return "Trusted certificate entry:\r\n" + cert.toString();
0560 }
0561 }
0562
0563 /**
0564 * Creates a KeyStore object of the given type, and encapsulates the given
0565 * provider implementation (SPI object) in it.
0566 *
0567 * @param keyStoreSpi the provider implementation.
0568 * @param provider the provider.
0569 * @param type the keystore type.
0570 */
0571 protected KeyStore(KeyStoreSpi keyStoreSpi, Provider provider,
0572 String type) {
0573 this .keyStoreSpi = keyStoreSpi;
0574 this .provider = provider;
0575 this .type = type;
0576 }
0577
0578 /**
0579 * Returns a keystore object of the specified type.
0580 *
0581 * <p> This method traverses the list of registered security Providers,
0582 * starting with the most preferred Provider.
0583 * A new KeyStore object encapsulating the
0584 * KeyStoreSpi implementation from the first
0585 * Provider that supports the specified type is returned.
0586 *
0587 * <p> Note that the list of registered providers may be retrieved via
0588 * the {@link Security#getProviders() Security.getProviders()} method.
0589 *
0590 * @param type the type of keystore.
0591 * See Appendix A in the <a href=
0592 * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
0593 * Java Cryptography Architecture API Specification & Reference </a>
0594 * for information about standard keystore types.
0595 *
0596 * @return a keystore object of the specified type.
0597 *
0598 * @exception KeyStoreException if no Provider supports a
0599 * KeyStoreSpi implementation for the
0600 * specified type.
0601 *
0602 * @see Provider
0603 */
0604 public static KeyStore getInstance(String type)
0605 throws KeyStoreException {
0606 try {
0607 Object[] objs = Security.getImpl(type, "KeyStore",
0608 (String) null);
0609 return new KeyStore((KeyStoreSpi) objs[0],
0610 (Provider) objs[1], type);
0611 } catch (NoSuchAlgorithmException nsae) {
0612 throw new KeyStoreException(type + " not found", nsae);
0613 } catch (NoSuchProviderException nspe) {
0614 throw new KeyStoreException(type + " not found", nspe);
0615 }
0616 }
0617
0618 /**
0619 * Returns a keystore object of the specified type.
0620 *
0621 * <p> A new KeyStore object encapsulating the
0622 * KeyStoreSpi implementation from the specified provider
0623 * is returned. The specified provider must be registered
0624 * in the security provider list.
0625 *
0626 * <p> Note that the list of registered providers may be retrieved via
0627 * the {@link Security#getProviders() Security.getProviders()} method.
0628 *
0629 * @param type the type of keystore.
0630 * See Appendix A in the <a href=
0631 * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
0632 * Java Cryptography Architecture API Specification & Reference </a>
0633 * for information about standard keystore types.
0634 *
0635 * @param provider the name of the provider.
0636 *
0637 * @return a keystore object of the specified type.
0638 *
0639 * @exception KeyStoreException if a KeyStoreSpi
0640 * implementation for the specified type is not
0641 * available from the specified provider.
0642 *
0643 * @exception NoSuchProviderException if the specified provider is not
0644 * registered in the security provider list.
0645 *
0646 * @exception IllegalArgumentException if the provider name is null
0647 * or empty.
0648 *
0649 * @see Provider
0650 */
0651 public static KeyStore getInstance(String type, String provider)
0652 throws KeyStoreException, NoSuchProviderException {
0653 if (provider == null || provider.length() == 0)
0654 throw new IllegalArgumentException("missing provider");
0655 try {
0656 Object[] objs = Security
0657 .getImpl(type, "KeyStore", provider);
0658 return new KeyStore((KeyStoreSpi) objs[0],
0659 (Provider) objs[1], type);
0660 } catch (NoSuchAlgorithmException nsae) {
0661 throw new KeyStoreException(type + " not found", nsae);
0662 }
0663 }
0664
0665 /**
0666 * Returns a keystore object of the specified type.
0667 *
0668 * <p> A new KeyStore object encapsulating the
0669 * KeyStoreSpi implementation from the specified Provider
0670 * object is returned. Note that the specified Provider object
0671 * does not have to be registered in the provider list.
0672 *
0673 * @param type the type of keystore.
0674 * See Appendix A in the <a href=
0675 * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
0676 * Java Cryptography Architecture API Specification & Reference </a>
0677 * for information about standard keystore types.
0678 *
0679 * @param provider the provider.
0680 *
0681 * @return a keystore object of the specified type.
0682 *
0683 * @exception KeyStoreException if KeyStoreSpi
0684 * implementation for the specified type is not available
0685 * from the specified Provider object.
0686 *
0687 * @exception IllegalArgumentException if the specified provider is null.
0688 *
0689 * @see Provider
0690 *
0691 * @since 1.4
0692 */
0693 public static KeyStore getInstance(String type, Provider provider)
0694 throws KeyStoreException {
0695 if (provider == null)
0696 throw new IllegalArgumentException("missing provider");
0697 try {
0698 Object[] objs = Security
0699 .getImpl(type, "KeyStore", provider);
0700 return new KeyStore((KeyStoreSpi) objs[0],
0701 (Provider) objs[1], type);
0702 } catch (NoSuchAlgorithmException nsae) {
0703 throw new KeyStoreException(type + " not found", nsae);
0704 }
0705 }
0706
0707 /**
0708 * Returns the default keystore type as specified in the Java security
0709 * properties file, or the string
0710 * "jks" (acronym for "Java keystore")
0711 * if no such property exists.
0712 * The Java security properties file is located in the file named
0713 * <JAVA_HOME>/lib/security/java.security.
0714 * <JAVA_HOME> refers to the value of the java.home system property,
0715 * and specifies the directory where the JRE is installed.
0716 *
0717 * <p>The default keystore type can be used by applications that do not
0718 * want to use a hard-coded keystore type when calling one of the
0719 * <code>getInstance</code> methods, and want to provide a default keystore
0720 * type in case a user does not specify its own.
0721 *
0722 * <p>The default keystore type can be changed by setting the value of the
0723 * "keystore.type" security property (in the Java security properties
0724 * file) to the desired keystore type.
0725 *
0726 * @return the default keystore type as specified in the
0727 * Java security properties file, or the string "jks"
0728 * if no such property exists.
0729 */
0730 public final static String getDefaultType() {
0731 String kstype;
0732 kstype = AccessController
0733 .doPrivileged(new PrivilegedAction<String>() {
0734 public String run() {
0735 return Security.getProperty(KEYSTORE_TYPE);
0736 }
0737 });
0738 if (kstype == null) {
0739 kstype = "jks";
0740 }
0741 return kstype;
0742 }
0743
0744 /**
0745 * Returns the provider of this keystore.
0746 *
0747 * @return the provider of this keystore.
0748 */
0749 public final Provider getProvider() {
0750 return this .provider;
0751 }
0752
0753 /**
0754 * Returns the type of this keystore.
0755 *
0756 * @return the type of this keystore.
0757 */
0758 public final String getType() {
0759 return this .type;
0760 }
0761
0762 /**
0763 * Returns the key associated with the given alias, using the given
0764 * password to recover it. The key must have been associated with
0765 * the alias by a call to <code>setKeyEntry</code>,
0766 * or by a call to <code>setEntry</code> with a
0767 * <code>PrivateKeyEntry</code> or <code>SecretKeyEntry</code>.
0768 *
0769 * @param alias the alias name
0770 * @param password the password for recovering the key
0771 *
0772 * @return the requested key, or null if the given alias does not exist
0773 * or does not identify a key-related entry.
0774 *
0775 * @exception KeyStoreException if the keystore has not been initialized
0776 * (loaded).
0777 * @exception NoSuchAlgorithmException if the algorithm for recovering the
0778 * key cannot be found
0779 * @exception UnrecoverableKeyException if the key cannot be recovered
0780 * (e.g., the given password is wrong).
0781 */
0782 public final Key getKey(String alias, char[] password)
0783 throws KeyStoreException, NoSuchAlgorithmException,
0784 UnrecoverableKeyException {
0785 if (!initialized) {
0786 throw new KeyStoreException("Uninitialized keystore");
0787 }
0788 return keyStoreSpi.engineGetKey(alias, password);
0789 }
0790
0791 /**
0792 * Returns the certificate chain associated with the given alias.
0793 * The certificate chain must have been associated with the alias
0794 * by a call to <code>setKeyEntry</code>,
0795 * or by a call to <code>setEntry</code> with a
0796 * <code>PrivateKeyEntry</code>.
0797 *
0798 * @param alias the alias name
0799 *
0800 * @return the certificate chain (ordered with the user's certificate first
0801 * and the root certificate authority last), or null if the given alias
0802 * does not exist or does not contain a certificate chain
0803 *
0804 * @exception KeyStoreException if the keystore has not been initialized
0805 * (loaded).
0806 */
0807 public final Certificate[] getCertificateChain(String alias)
0808 throws KeyStoreException {
0809 if (!initialized) {
0810 throw new KeyStoreException("Uninitialized keystore");
0811 }
0812 return keyStoreSpi.engineGetCertificateChain(alias);
0813 }
0814
0815 /**
0816 * Returns the certificate associated with the given alias.
0817 *
0818 * <p> If the given alias name identifies an entry
0819 * created by a call to <code>setCertificateEntry</code>,
0820 * or created by a call to <code>setEntry</code> with a
0821 * <code>TrustedCertificateEntry</code>,
0822 * then the trusted certificate contained in that entry is returned.
0823 *
0824 * <p> If the given alias name identifies an entry
0825 * created by a call to <code>setKeyEntry</code>,
0826 * or created by a call to <code>setEntry</code> with a
0827 * <code>PrivateKeyEntry</code>,
0828 * then the first element of the certificate chain in that entry
0829 * is returned.
0830 *
0831 * @param alias the alias name
0832 *
0833 * @return the certificate, or null if the given alias does not exist or
0834 * does not contain a certificate.
0835 *
0836 * @exception KeyStoreException if the keystore has not been initialized
0837 * (loaded).
0838 */
0839 public final Certificate getCertificate(String alias)
0840 throws KeyStoreException {
0841 if (!initialized) {
0842 throw new KeyStoreException("Uninitialized keystore");
0843 }
0844 return keyStoreSpi.engineGetCertificate(alias);
0845 }
0846
0847 /**
0848 * Returns the creation date of the entry identified by the given alias.
0849 *
0850 * @param alias the alias name
0851 *
0852 * @return the creation date of this entry, or null if the given alias does
0853 * not exist
0854 *
0855 * @exception KeyStoreException if the keystore has not been initialized
0856 * (loaded).
0857 */
0858 public final Date getCreationDate(String alias)
0859 throws KeyStoreException {
0860 if (!initialized) {
0861 throw new KeyStoreException("Uninitialized keystore");
0862 }
0863 return keyStoreSpi.engineGetCreationDate(alias);
0864 }
0865
0866 /**
0867 * Assigns the given key to the given alias, protecting it with the given
0868 * password.
0869 *
0870 * <p>If the given key is of type <code>java.security.PrivateKey</code>,
0871 * it must be accompanied by a certificate chain certifying the
0872 * corresponding public key.
0873 *
0874 * <p>If the given alias already exists, the keystore information
0875 * associated with it is overridden by the given key (and possibly
0876 * certificate chain).
0877 *
0878 * @param alias the alias name
0879 * @param key the key to be associated with the alias
0880 * @param password the password to protect the key
0881 * @param chain the certificate chain for the corresponding public
0882 * key (only required if the given key is of type
0883 * <code>java.security.PrivateKey</code>).
0884 *
0885 * @exception KeyStoreException if the keystore has not been initialized
0886 * (loaded), the given key cannot be protected, or this operation fails
0887 * for some other reason
0888 */
0889 public final void setKeyEntry(String alias, Key key,
0890 char[] password, Certificate[] chain)
0891 throws KeyStoreException {
0892 if (!initialized) {
0893 throw new KeyStoreException("Uninitialized keystore");
0894 }
0895 if ((key instanceof PrivateKey)
0896 && (chain == null || chain.length == 0)) {
0897 throw new IllegalArgumentException("Private key must be "
0898 + "accompanied by certificate " + "chain");
0899 }
0900 keyStoreSpi.engineSetKeyEntry(alias, key, password, chain);
0901 }
0902
0903 /**
0904 * Assigns the given key (that has already been protected) to the given
0905 * alias.
0906 *
0907 * <p>If the protected key is of type
0908 * <code>java.security.PrivateKey</code>, it must be accompanied by a
0909 * certificate chain certifying the corresponding public key. If the
0910 * underlying keystore implementation is of type <code>jks</code>,
0911 * <code>key</code> must be encoded as an
0912 * <code>EncryptedPrivateKeyInfo</code> as defined in the PKCS #8 standard.
0913 *
0914 * <p>If the given alias already exists, the keystore information
0915 * associated with it is overridden by the given key (and possibly
0916 * certificate chain).
0917 *
0918 * @param alias the alias name
0919 * @param key the key (in protected format) to be associated with the alias
0920 * @param chain the certificate chain for the corresponding public
0921 * key (only useful if the protected key is of type
0922 * <code>java.security.PrivateKey</code>).
0923 *
0924 * @exception KeyStoreException if the keystore has not been initialized
0925 * (loaded), or if this operation fails for some other reason.
0926 */
0927 public final void setKeyEntry(String alias, byte[] key,
0928 Certificate[] chain) throws KeyStoreException {
0929 if (!initialized) {
0930 throw new KeyStoreException("Uninitialized keystore");
0931 }
0932 keyStoreSpi.engineSetKeyEntry(alias, key, chain);
0933 }
0934
0935 /**
0936 * Assigns the given trusted certificate to the given alias.
0937 *
0938 * <p> If the given alias identifies an existing entry
0939 * created by a call to <code>setCertificateEntry</code>,
0940 * or created by a call to <code>setEntry</code> with a
0941 * <code>TrustedCertificateEntry</code>,
0942 * the trusted certificate in the existing entry
0943 * is overridden by the given certificate.
0944 *
0945 * @param alias the alias name
0946 * @param cert the certificate
0947 *
0948 * @exception KeyStoreException if the keystore has not been initialized,
0949 * or the given alias already exists and does not identify an
0950 * entry containing a trusted certificate,
0951 * or this operation fails for some other reason.
0952 */
0953 public final void setCertificateEntry(String alias, Certificate cert)
0954 throws KeyStoreException {
0955 if (!initialized) {
0956 throw new KeyStoreException("Uninitialized keystore");
0957 }
0958 keyStoreSpi.engineSetCertificateEntry(alias, cert);
0959 }
0960
0961 /**
0962 * Deletes the entry identified by the given alias from this keystore.
0963 *
0964 * @param alias the alias name
0965 *
0966 * @exception KeyStoreException if the keystore has not been initialized,
0967 * or if the entry cannot be removed.
0968 */
0969 public final void deleteEntry(String alias)
0970 throws KeyStoreException {
0971 if (!initialized) {
0972 throw new KeyStoreException("Uninitialized keystore");
0973 }
0974 keyStoreSpi.engineDeleteEntry(alias);
0975 }
0976
0977 /**
0978 * Lists all the alias names of this keystore.
0979 *
0980 * @return enumeration of the alias names
0981 *
0982 * @exception KeyStoreException if the keystore has not been initialized
0983 * (loaded).
0984 */
0985 public final Enumeration<String> aliases() throws KeyStoreException {
0986 if (!initialized) {
0987 throw new KeyStoreException("Uninitialized keystore");
0988 }
0989 return keyStoreSpi.engineAliases();
0990 }
0991
0992 /**
0993 * Checks if the given alias exists in this keystore.
0994 *
0995 * @param alias the alias name
0996 *
0997 * @return true if the alias exists, false otherwise
0998 *
0999 * @exception KeyStoreException if the keystore has not been initialized
1000 * (loaded).
1001 */
1002 public final boolean containsAlias(String alias)
1003 throws KeyStoreException {
1004 if (!initialized) {
1005 throw new KeyStoreException("Uninitialized keystore");
1006 }
1007 return keyStoreSpi.engineContainsAlias(alias);
1008 }
1009
1010 /**
1011 * Retrieves the number of entries in this keystore.
1012 *
1013 * @return the number of entries in this keystore
1014 *
1015 * @exception KeyStoreException if the keystore has not been initialized
1016 * (loaded).
1017 */
1018 public final int size() throws KeyStoreException {
1019 if (!initialized) {
1020 throw new KeyStoreException("Uninitialized keystore");
1021 }
1022 return keyStoreSpi.engineSize();
1023 }
1024
1025 /**
1026 * Returns true if the entry identified by the given alias
1027 * was created by a call to <code>setKeyEntry</code>,
1028 * or created by a call to <code>setEntry</code> with a
1029 * <code>PrivateKeyEntry</code> or a <code>SecretKeyEntry</code>.
1030 *
1031 * @param alias the alias for the keystore entry to be checked
1032 *
1033 * @return true if the entry identified by the given alias is a
1034 * key-related entry, false otherwise.
1035 *
1036 * @exception KeyStoreException if the keystore has not been initialized
1037 * (loaded).
1038 */
1039 public final boolean isKeyEntry(String alias)
1040 throws KeyStoreException {
1041 if (!initialized) {
1042 throw new KeyStoreException("Uninitialized keystore");
1043 }
1044 return keyStoreSpi.engineIsKeyEntry(alias);
1045 }
1046
1047 /**
1048 * Returns true if the entry identified by the given alias
1049 * was created by a call to <code>setCertificateEntry</code>,
1050 * or created by a call to <code>setEntry</code> with a
1051 * <code>TrustedCertificateEntry</code>.
1052 *
1053 * @param alias the alias for the keystore entry to be checked
1054 *
1055 * @return true if the entry identified by the given alias contains a
1056 * trusted certificate, false otherwise.
1057 *
1058 * @exception KeyStoreException if the keystore has not been initialized
1059 * (loaded).
1060 */
1061 public final boolean isCertificateEntry(String alias)
1062 throws KeyStoreException {
1063 if (!initialized) {
1064 throw new KeyStoreException("Uninitialized keystore");
1065 }
1066 return keyStoreSpi.engineIsCertificateEntry(alias);
1067 }
1068
1069 /**
1070 * Returns the (alias) name of the first keystore entry whose certificate
1071 * matches the given certificate.
1072 *
1073 * <p> This method attempts to match the given certificate with each
1074 * keystore entry. If the entry being considered was
1075 * created by a call to <code>setCertificateEntry</code>,
1076 * or created by a call to <code>setEntry</code> with a
1077 * <code>TrustedCertificateEntry</code>,
1078 * then the given certificate is compared to that entry's certificate.
1079 *
1080 * <p> If the entry being considered was
1081 * created by a call to <code>setKeyEntry</code>,
1082 * or created by a call to <code>setEntry</code> with a
1083 * <code>PrivateKeyEntry</code>,
1084 * then the given certificate is compared to the first
1085 * element of that entry's certificate chain.
1086 *
1087 * @param cert the certificate to match with.
1088 *
1089 * @return the alias name of the first entry with a matching certificate,
1090 * or null if no such entry exists in this keystore.
1091 *
1092 * @exception KeyStoreException if the keystore has not been initialized
1093 * (loaded).
1094 */
1095 public final String getCertificateAlias(Certificate cert)
1096 throws KeyStoreException {
1097 if (!initialized) {
1098 throw new KeyStoreException("Uninitialized keystore");
1099 }
1100 return keyStoreSpi.engineGetCertificateAlias(cert);
1101 }
1102
1103 /**
1104 * Stores this keystore to the given output stream, and protects its
1105 * integrity with the given password.
1106 *
1107 * @param stream the output stream to which this keystore is written.
1108 * @param password the password to generate the keystore integrity check
1109 *
1110 * @exception KeyStoreException if the keystore has not been initialized
1111 * (loaded).
1112 * @exception IOException if there was an I/O problem with data
1113 * @exception NoSuchAlgorithmException if the appropriate data integrity
1114 * algorithm could not be found
1115 * @exception CertificateException if any of the certificates included in
1116 * the keystore data could not be stored
1117 */
1118 public final void store(OutputStream stream, char[] password)
1119 throws KeyStoreException, IOException,
1120 NoSuchAlgorithmException, CertificateException {
1121 if (!initialized) {
1122 throw new KeyStoreException("Uninitialized keystore");
1123 }
1124 keyStoreSpi.engineStore(stream, password);
1125 }
1126
1127 /**
1128 * Stores this keystore using the given <code>LoadStoreParameter</code>.
1129 *
1130 * @param param the <code>LoadStoreParameter</code>
1131 * that specifies how to store the keystore,
1132 * which may be <code>null</code>
1133 *
1134 * @exception IllegalArgumentException if the given
1135 * <code>LoadStoreParameter</code>
1136 * input is not recognized
1137 * @exception KeyStoreException if the keystore has not been initialized
1138 * (loaded)
1139 * @exception IOException if there was an I/O problem with data
1140 * @exception NoSuchAlgorithmException if the appropriate data integrity
1141 * algorithm could not be found
1142 * @exception CertificateException if any of the certificates included in
1143 * the keystore data could not be stored
1144 *
1145 * @since 1.5
1146 */
1147 public final void store(LoadStoreParameter param)
1148 throws KeyStoreException, IOException,
1149 NoSuchAlgorithmException, CertificateException {
1150 if (!initialized) {
1151 throw new KeyStoreException("Uninitialized keystore");
1152 }
1153 keyStoreSpi.engineStore(param);
1154 }
1155
1156 /**
1157 * Loads this KeyStore from the given input stream.
1158 *
1159 * <p>A password may be given to unlock the keystore
1160 * (e.g. the keystore resides on a hardware token device),
1161 * or to check the integrity of the keystore data.
1162 * If a password is not given for integrity checking,
1163 * then integrity checking is not performed.
1164 *
1165 * <p>In order to create an empty keystore, or if the keystore cannot
1166 * be initialized from a stream, pass <code>null</code>
1167 * as the <code>stream</code> argument.
1168 *
1169 * <p> Note that if this keystore has already been loaded, it is
1170 * reinitialized and loaded again from the given input stream.
1171 *
1172 * @param stream the input stream from which the keystore is loaded,
1173 * or <code>null</code>
1174 * @param password the password used to check the integrity of
1175 * the keystore, the password used to unlock the keystore,
1176 * or <code>null</code>
1177 *
1178 * @exception IOException if there is an I/O or format problem with the
1179 * keystore data, if a password is required but not given,
1180 * or if the given password was incorrect. If the error is due to a
1181 * wrong password, the {@link Throwable#getCause cause} of the
1182 * <code>IOException</code> should be an
1183 * <code>UnrecoverableKeyException</code>
1184 * @exception NoSuchAlgorithmException if the algorithm used to check
1185 * the integrity of the keystore cannot be found
1186 * @exception CertificateException if any of the certificates in the
1187 * keystore could not be loaded
1188 */
1189 public final void load(InputStream stream, char[] password)
1190 throws IOException, NoSuchAlgorithmException,
1191 CertificateException {
1192 keyStoreSpi.engineLoad(stream, password);
1193 initialized = true;
1194 }
1195
1196 /**
1197 * Loads this keystore using the given <code>LoadStoreParameter</code>.
1198 *
1199 * <p> Note that if this KeyStore has already been loaded, it is
1200 * reinitialized and loaded again from the given parameter.
1201 *
1202 * @param param the <code>LoadStoreParameter</code>
1203 * that specifies how to load the keystore,
1204 * which may be <code>null</code>
1205 *
1206 * @exception IllegalArgumentException if the given
1207 * <code>LoadStoreParameter</code>
1208 * input is not recognized
1209 * @exception IOException if there is an I/O or format problem with the
1210 * keystore data. If the error is due to an incorrect
1211 * <code>ProtectionParameter</code> (e.g. wrong password)
1212 * the {@link Throwable#getCause cause} of the
1213 * <code>IOException</code> should be an
1214 * <code>UnrecoverableKeyException</code>
1215 * @exception NoSuchAlgorithmException if the algorithm used to check
1216 * the integrity of the keystore cannot be found
1217 * @exception CertificateException if any of the certificates in the
1218 * keystore could not be loaded
1219 *
1220 * @since 1.5
1221 */
1222 public final void load(LoadStoreParameter param)
1223 throws IOException, NoSuchAlgorithmException,
1224 CertificateException {
1225
1226 keyStoreSpi.engineLoad(param);
1227 initialized = true;
1228 }
1229
1230 /**
1231 * Gets a keystore <code>Entry</code> for the specified alias
1232 * with the specified protection parameter.
1233 *
1234 * @param alias get the keystore <code>Entry</code> for this alias
1235 * @param protParam the <code>ProtectionParameter</code>
1236 * used to protect the <code>Entry</code>,
1237 * which may be <code>null</code>
1238 *
1239 * @return the keystore <code>Entry</code> for the specified alias,
1240 * or <code>null</code> if there is no such entry
1241 *
1242 * @exception NullPointerException if
1243 * <code>alias</code> is <code>null</code>
1244 * @exception NoSuchAlgorithmException if the algorithm for recovering the
1245 * entry cannot be found
1246 * @exception UnrecoverableEntryException if the specified
1247 * <code>protParam</code> were insufficient or invalid
1248 * @exception UnrecoverableKeyException if the entry is a
1249 * <code>PrivateKeyEntry</code> or <code>SecretKeyEntry</code>
1250 * and the specified <code>protParam</code> does not contain
1251 * the information needed to recover the key (e.g. wrong password)
1252 * @exception KeyStoreException if the keystore has not been initialized
1253 * (loaded).
1254 * @see #setEntry(String, KeyStore.Entry, KeyStore.ProtectionParameter)
1255 *
1256 * @since 1.5
1257 */
1258 public final Entry getEntry(String alias,
1259 ProtectionParameter protParam)
1260 throws NoSuchAlgorithmException,
1261 UnrecoverableEntryException, KeyStoreException {
1262
1263 if (alias == null) {
1264 throw new NullPointerException("invalid null input");
1265 }
1266 if (!initialized) {
1267 throw new KeyStoreException("Uninitialized keystore");
1268 }
1269 return keyStoreSpi.engineGetEntry(alias, protParam);
1270 }
1271
1272 /**
1273 * Saves a keystore <code>Entry</code> under the specified alias.
1274 * The protection parameter is used to protect the
1275 * <code>Entry</code>.
1276 *
1277 * <p> If an entry already exists for the specified alias,
1278 * it is overridden.
1279 *
1280 * @param alias save the keystore <code>Entry</code> under this alias
1281 * @param entry the <code>Entry</code> to save
1282 * @param protParam the <code>ProtectionParameter</code>
1283 * used to protect the <code>Entry</code>,
1284 * which may be <code>null</code>
1285 *
1286 * @exception NullPointerException if
1287 * <code>alias</code> or <code>entry</code>
1288 * is <code>null</code>
1289 * @exception KeyStoreException if the keystore has not been initialized
1290 * (loaded), or if this operation fails for some other reason
1291 *
1292 * @see #getEntry(String, KeyStore.ProtectionParameter)
1293 *
1294 * @since 1.5
1295 */
1296 public final void setEntry(String alias, Entry entry,
1297 ProtectionParameter protParam) throws KeyStoreException {
1298 if (alias == null || entry == null) {
1299 throw new NullPointerException("invalid null input");
1300 }
1301 if (!initialized) {
1302 throw new KeyStoreException("Uninitialized keystore");
1303 }
1304 keyStoreSpi.engineSetEntry(alias, entry, protParam);
1305 }
1306
1307 /**
1308 * Determines if the keystore <code>Entry</code> for the specified
1309 * <code>alias</code> is an instance or subclass of the specified
1310 * <code>entryClass</code>.
1311 *
1312 * @param alias the alias name
1313 * @param entryClass the entry class
1314 *
1315 * @return true if the keystore <code>Entry</code> for the specified
1316 * <code>alias</code> is an instance or subclass of the
1317 * specified <code>entryClass</code>, false otherwise
1318 *
1319 * @exception NullPointerException if
1320 * <code>alias</code> or <code>entryClass</code>
1321 * is <code>null</code>
1322 * @exception KeyStoreException if the keystore has not been
1323 * initialized (loaded)
1324 *
1325 * @since 1.5
1326 */
1327 public final boolean entryInstanceOf(String alias,
1328 Class<? extends KeyStore.Entry> entryClass)
1329 throws KeyStoreException {
1330
1331 if (alias == null || entryClass == null) {
1332 throw new NullPointerException("invalid null input");
1333 }
1334 if (!initialized) {
1335 throw new KeyStoreException("Uninitialized keystore");
1336 }
1337 return keyStoreSpi.engineEntryInstanceOf(alias, entryClass);
1338 }
1339
1340 /**
1341 * A description of a to-be-instantiated KeyStore object.
1342 *
1343 * <p>An instance of this class encapsulates the information needed to
1344 * instantiate and initialize a KeyStore object. That process is
1345 * triggered when the {@linkplain #getKeyStore} method is called.
1346 *
1347 * <p>This makes it possible to decouple configuration from KeyStore
1348 * object creation and e.g. delay a password prompt until it is
1349 * needed.
1350 *
1351 * @see KeyStore
1352 * @see javax.net.ssl.KeyStoreBuilderParameters
1353 * @since 1.5
1354 */
1355 public static abstract class Builder {
1356
1357 // maximum times to try the callbackhandler if the password is wrong
1358 static final int MAX_CALLBACK_TRIES = 3;
1359
1360 /**
1361 * Construct a new Builder.
1362 */
1363 protected Builder() {
1364 // empty
1365 }
1366
1367 /**
1368 * Returns the KeyStore described by this object.
1369 *
1370 * @exception KeyStoreException if an error occured during the
1371 * operation, for example if the KeyStore could not be
1372 * instantiated or loaded
1373 */
1374 public abstract KeyStore getKeyStore() throws KeyStoreException;
1375
1376 /**
1377 * Returns the ProtectionParameters that should be used to obtain
1378 * the {@link KeyStore.Entry Entry} with the given alias.
1379 * The <code>getKeyStore</code> method must be invoked before this
1380 * method may be called.
1381 *
1382 * @return the ProtectionParameters that should be used to obtain
1383 * the {@link KeyStore.Entry Entry} with the given alias.
1384 * @param alias the alias of the KeyStore entry
1385 * @throws NullPointerException if alias is null
1386 * @throws KeyStoreException if an error occured during the
1387 * operation
1388 * @throws IllegalStateException if the getKeyStore method has
1389 * not been invoked prior to calling this method
1390 */
1391 public abstract ProtectionParameter getProtectionParameter(
1392 String alias) throws KeyStoreException;
1393
1394 /**
1395 * Returns a new Builder that encapsulates the given KeyStore.
1396 * The {@linkplain #getKeyStore} method of the returned object
1397 * will return <code>keyStore</code>, the {@linkplain
1398 * #getProtectionParameter getProtectionParameter()} method will
1399 * return <code>protectionParameters</code>.
1400 *
1401 * <p> This is useful if an existing KeyStore object needs to be
1402 * used with Builder-based APIs.
1403 *
1404 * @return a new Builder object
1405 * @param keyStore the KeyStore to be encapsulated
1406 * @param protectionParameter the ProtectionParameter used to
1407 * protect the KeyStore entries
1408 * @throws NullPointerException if keyStore or
1409 * protectionParameters is null
1410 * @throws IllegalArgumentException if the keyStore has not been
1411 * initialized
1412 */
1413 public static Builder newInstance(final KeyStore keyStore,
1414 final ProtectionParameter protectionParameter) {
1415 if ((keyStore == null) || (protectionParameter == null)) {
1416 throw new NullPointerException();
1417 }
1418 if (keyStore.initialized == false) {
1419 throw new IllegalArgumentException(
1420 "KeyStore not initialized");
1421 }
1422 return new Builder() {
1423 private volatile boolean getCalled;
1424
1425 public KeyStore getKeyStore() {
1426 getCalled = true;
1427 return keyStore;
1428 }
1429
1430 public ProtectionParameter getProtectionParameter(
1431 String alias) {
1432 if (alias == null) {
1433 throw new NullPointerException();
1434 }
1435 if (getCalled == false) {
1436 throw new IllegalStateException(
1437 "getKeyStore() must be called first");
1438 }
1439 return protectionParameter;
1440 }
1441 };
1442 }
1443
1444 /**
1445 * Returns a new Builder object.
1446 *
1447 * <p>The first call to the {@link #getKeyStore} method on the returned
1448 * builder will create a KeyStore of type <code>type</code> and call
1449 * its {@link KeyStore#load load()} method.
1450 * The <code>inputStream</code> argument is constructed from
1451 * <code>file</code>.
1452 * If <code>protection</code> is a
1453 * <code>PasswordProtection</code>, the password is obtained by
1454 * calling the <code>getPassword</code> method.
1455 * Otherwise, if <code>protection</code> is a
1456 * <code>CallbackHandlerProtection</code>, the password is obtained
1457 * by invoking the CallbackHandler.
1458 *
1459 * <p>Subsequent calls to {@link #getKeyStore} return the same object
1460 * as the initial call. If the initial call to failed with a
1461 * KeyStoreException, subsequent calls also throw a
1462 * KeyStoreException.
1463 *
1464 * <p>The KeyStore is instantiated from <code>provider</code> if
1465 * non-null. Otherwise, all installed providers are searched.
1466 *
1467 * <p>Calls to {@link #getProtectionParameter getProtectionParameter()}
1468 * will return a {@link KeyStore.PasswordProtection PasswordProtection}
1469 * object encapsulating the password that was used to invoke the
1470 * <code>load</code> method.
1471 *
1472 * <p><em>Note</em> that the {@link #getKeyStore} method is executed
1473 * within the {@link AccessControlContext} of the code invoking this
1474 * method.
1475 *
1476 * @return a new Builder object
1477 * @param type the type of KeyStore to be constructed
1478 * @param provider the provider from which the KeyStore is to
1479 * be instantiated (or null)
1480 * @param file the File that contains the KeyStore data
1481 * @param protection the ProtectionParameter securing the KeyStore data
1482 * @throws NullPointerException if type, file or protection is null
1483 * @throws IllegalArgumentException if protection is not an instance
1484 * of either PasswordProtection or CallbackHandlerProtection; or
1485 * if file does not exist or does not refer to a normal file
1486 */
1487 public static Builder newInstance(String type,
1488 Provider provider, File file,
1489 ProtectionParameter protection) {
1490 if ((type == null) || (file == null)
1491 || (protection == null)) {
1492 throw new NullPointerException();
1493 }
1494 if ((protection instanceof PasswordProtection == false)
1495 && (protection instanceof CallbackHandlerProtection == false)) {
1496 throw new IllegalArgumentException(
1497 "Protection must be PasswordProtection or "
1498 + "CallbackHandlerProtection");
1499 }
1500 if (file.isFile() == false) {
1501 throw new IllegalArgumentException(
1502 "File does not exist or it does not refer "
1503 + "to a normal file: " + file);
1504 }
1505 return new FileBuilder(type, provider, file, protection,
1506 AccessController.getContext());
1507 }
1508
1509 private static final class FileBuilder extends Builder {
1510
1511 private final String type;
1512 private final Provider provider;
1513 private final File file;
1514 private ProtectionParameter protection;
1515 private ProtectionParameter keyProtection;
1516 private final AccessControlContext context;
1517
1518 private KeyStore keyStore;
1519
1520 private Throwable oldException;
1521
1522 FileBuilder(String type, Provider provider, File file,
1523 ProtectionParameter protection,
1524 AccessControlContext context) {
1525 this .type = type;
1526 this .provider = provider;
1527 this .file = file;
1528 this .protection = protection;
1529 this .context = context;
1530 }
1531
1532 public synchronized KeyStore getKeyStore()
1533 throws KeyStoreException {
1534 if (keyStore != null) {
1535 return keyStore;
1536 }
1537 if (oldException != null) {
1538 throw new KeyStoreException(
1539 "Previous KeyStore instantiation failed",
1540 oldException);
1541 }
1542 PrivilegedExceptionAction<KeyStore> action = new PrivilegedExceptionAction<KeyStore>() {
1543 public KeyStore run() throws Exception {
1544 if (protection instanceof CallbackHandlerProtection == false) {
1545 return run0();
1546 }
1547 // when using a CallbackHandler,
1548 // reprompt if the password is wrong
1549 int tries = 0;
1550 while (true) {
1551 tries++;
1552 try {
1553 return run0();
1554 } catch (IOException e) {
1555 if ((tries < MAX_CALLBACK_TRIES)
1556 && (e.getCause() instanceof UnrecoverableKeyException)) {
1557 continue;
1558 }
1559 throw e;
1560 }
1561 }
1562 }
1563
1564 public KeyStore run0() throws Exception {
1565 KeyStore ks;
1566 if (provider == null) {
1567 ks = KeyStore.getInstance(type);
1568 } else {
1569 ks = KeyStore.getInstance(type, provider);
1570 }
1571 InputStream in = null;
1572 char[] password = null;
1573 try {
1574 in = new FileInputStream(file);
1575 if (protection instanceof PasswordProtection) {
1576 password = ((PasswordProtection) protection)
1577 .getPassword();
1578 keyProtection = protection;
1579 } else {
1580 CallbackHandler handler = ((CallbackHandlerProtection) protection)
1581 .getCallbackHandler();
1582 PasswordCallback callback = new PasswordCallback(
1583 "Password for keystore "
1584 + file.getName(), false);
1585 handler
1586 .handle(new Callback[] { callback });
1587 password = callback.getPassword();
1588 if (password == null) {
1589 throw new KeyStoreException(
1590 "No password" + " provided");
1591 }
1592 callback.clearPassword();
1593 keyProtection = new PasswordProtection(
1594 password);
1595 }
1596 ks.load(in, password);
1597 return ks;
1598 } finally {
1599 if (in != null) {
1600 in.close();
1601 }
1602 }
1603 }
1604 };
1605 try {
1606 keyStore = AccessController.doPrivileged(action,
1607 context);
1608 return keyStore;
1609 } catch (PrivilegedActionException e) {
1610 oldException = e.getCause();
1611 throw new KeyStoreException(
1612 "KeyStore instantiation failed",
1613 oldException);
1614 }
1615 }
1616
1617 public synchronized ProtectionParameter getProtectionParameter(
1618 String alias) {
1619 if (alias == null) {
1620 throw new NullPointerException();
1621 }
1622 if (keyStore == null) {
1623 throw new IllegalStateException(
1624 "getKeyStore() must be called first");
1625 }
1626 return keyProtection;
1627 }
1628 }
1629
1630 /**
1631 * Returns a new Builder object.
1632 *
1633 * <p>Each call to the {@link #getKeyStore} method on the returned
1634 * builder will return a new KeyStore object of type <code>type</code>.
1635 * Its {@link KeyStore#load(KeyStore.LoadStoreParameter) load()}
1636 * method is invoked using a
1637 * <code>LoadStoreParameter</code> that encapsulates
1638 * <code>protection</code>.
1639 *
1640 * <p>The KeyStore is instantiated from <code>provider</code> if
1641 * non-null. Otherwise, all installed providers are searched.
1642 *
1643 * <p>Calls to {@link #getProtectionParameter getProtectionParameter()}
1644 * will return <code>protection</code>.
1645 *
1646 * <p><em>Note</em> that the {@link #getKeyStore} method is executed
1647 * within the {@link AccessControlContext} of the code invoking this
1648 * method.
1649 *
1650 * @return a new Builder object
1651 * @param type the type of KeyStore to be constructed
1652 * @param provider the provider from which the KeyStore is to
1653 * be instantiated (or null)
1654 * @param protection the ProtectionParameter securing the Keystore
1655 * @throws NullPointerException if type or protection is null
1656 */
1657 public static Builder newInstance(final String type,
1658 final Provider provider,
1659 final ProtectionParameter protection) {
1660 if ((type == null) || (protection == null)) {
1661 throw new NullPointerException();
1662 }
1663 final AccessControlContext context = AccessController
1664 .getContext();
1665 return new Builder() {
1666 private volatile boolean getCalled;
1667 private IOException oldException;
1668
1669 private final PrivilegedExceptionAction<KeyStore> action = new PrivilegedExceptionAction<KeyStore>() {
1670
1671 public KeyStore run() throws Exception {
1672 KeyStore ks;
1673 if (provider == null) {
1674 ks = KeyStore.getInstance(type);
1675 } else {
1676 ks = KeyStore.getInstance(type, provider);
1677 }
1678 LoadStoreParameter param = new SimpleLoadStoreParameter(
1679 protection);
1680 if (protection instanceof CallbackHandlerProtection == false) {
1681 ks.load(param);
1682 } else {
1683 // when using a CallbackHandler,
1684 // reprompt if the password is wrong
1685 int tries = 0;
1686 while (true) {
1687 tries++;
1688 try {
1689 ks.load(param);
1690 break;
1691 } catch (IOException e) {
1692 if (e.getCause() instanceof UnrecoverableKeyException) {
1693 if (tries < MAX_CALLBACK_TRIES) {
1694 continue;
1695 } else {
1696 oldException = e;
1697 }
1698 }
1699 throw e;
1700 }
1701 }
1702 }
1703 getCalled = true;
1704 return ks;
1705 }
1706 };
1707
1708 public synchronized KeyStore getKeyStore()
1709 throws KeyStoreException {
1710 if (oldException != null) {
1711 throw new KeyStoreException(
1712 "Previous KeyStore instantiation failed",
1713 oldException);
1714 }
1715 try {
1716 return AccessController.doPrivileged(action);
1717 } catch (PrivilegedActionException e) {
1718 Throwable cause = e.getCause();
1719 throw new KeyStoreException(
1720 "KeyStore instantiation failed", cause);
1721 }
1722 }
1723
1724 public ProtectionParameter getProtectionParameter(
1725 String alias) {
1726 if (alias == null) {
1727 throw new NullPointerException();
1728 }
1729 if (getCalled == false) {
1730 throw new IllegalStateException(
1731 "getKeyStore() must be called first");
1732 }
1733 return protection;
1734 }
1735 };
1736 }
1737
1738 }
1739
1740 static class SimpleLoadStoreParameter implements LoadStoreParameter {
1741
1742 private final ProtectionParameter protection;
1743
1744 SimpleLoadStoreParameter(ProtectionParameter protection) {
1745 this .protection = protection;
1746 }
1747
1748 public ProtectionParameter getProtectionParameter() {
1749 return protection;
1750 }
1751 }
1752
1753 }
|