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