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