Save This Page
Home » openjdk-7 » java » security » [javadoc | source]
    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   }

Save This Page
Home » openjdk-7 » java » security » [javadoc | source]