1 /*
   2  * Copyright (c) 1997, 2010, 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 }