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