1 /* 2 * Copyright (c) 1997, 2015, 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} property to determine 847 * the preferred provider order for the specified algorithm. This 848 * may be different than the order of providers returned by 849 * {@link Security#getProviders() Security.getProviders()}. 850 * 851 * @param type the type of keystore. 852 * See the KeyStore section in the <a href= 853 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore"> 854 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 855 * for information about standard keystore types. 856 * 857 * @return a keystore object of the specified type. 858 * 859 * @exception KeyStoreException if no Provider supports a 860 * KeyStoreSpi implementation for the 861 * specified type. 862 * 863 * @see Provider 864 */ 865 public static KeyStore getInstance(String type) 866 throws KeyStoreException 867 { 868 try { 869 Object[] objs = Security.getImpl(type, "KeyStore", (String)null); 870 return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type); 871 } catch (NoSuchAlgorithmException nsae) { 872 throw new KeyStoreException(type + " not found", nsae); 873 } catch (NoSuchProviderException nspe) { 874 throw new KeyStoreException(type + " not found", nspe); 875 } 876 } 877 878 /** 879 * Returns a keystore object of the specified type. 880 * 881 * <p> A new KeyStore object encapsulating the 882 * KeyStoreSpi implementation from the specified provider 883 * is returned. The specified provider must be registered 884 * in the security provider list. 885 * 886 * <p> Note that the list of registered providers may be retrieved via 887 * the {@link Security#getProviders() Security.getProviders()} method. 888 * 889 * @param type the type of keystore. 890 * See the KeyStore section in the <a href= 891 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore"> 892 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 893 * for information about standard keystore types. 894 * 895 * @param provider the name of the provider. 896 * 897 * @return a keystore object of the specified type. 898 * 899 * @exception KeyStoreException if a KeyStoreSpi 900 * implementation for the specified type is not 901 * available from the specified provider. 902 * 903 * @exception NoSuchProviderException if the specified provider is not 904 * registered in the security provider list. 905 * 906 * @exception IllegalArgumentException if the provider name is null 907 * or empty. 908 * 909 * @see Provider 910 */ 911 public static KeyStore getInstance(String type, String provider) 912 throws KeyStoreException, NoSuchProviderException 913 { 914 if (provider == null || provider.length() == 0) 915 throw new IllegalArgumentException("missing provider"); 916 try { 917 Object[] objs = Security.getImpl(type, "KeyStore", provider); 918 return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type); 919 } catch (NoSuchAlgorithmException nsae) { 920 throw new KeyStoreException(type + " not found", nsae); 921 } 922 } 923 924 /** 925 * Returns a keystore object of the specified type. 926 * 927 * <p> A new KeyStore object encapsulating the 928 * KeyStoreSpi implementation from the specified Provider 929 * object is returned. Note that the specified Provider object 930 * does not have to be registered in the provider list. 931 * 932 * @param type the type of keystore. 933 * See the KeyStore section in the <a href= 934 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore"> 935 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 936 * for information about standard keystore types. 937 * 938 * @param provider the provider. 939 * 940 * @return a keystore object of the specified type. 941 * 942 * @exception KeyStoreException if KeyStoreSpi 943 * implementation for the specified type is not available 944 * from the specified Provider object. 945 * 946 * @exception IllegalArgumentException if the specified provider is null. 947 * 948 * @see Provider 949 * 950 * @since 1.4 951 */ 952 public static KeyStore getInstance(String type, Provider provider) 953 throws KeyStoreException 954 { 955 if (provider == null) 956 throw new IllegalArgumentException("missing provider"); 957 try { 958 Object[] objs = Security.getImpl(type, "KeyStore", provider); 959 return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type); 960 } catch (NoSuchAlgorithmException nsae) { 961 throw new KeyStoreException(type + " not found", nsae); 962 } 963 } 964 965 /** 966 * Returns the default keystore type as specified by the 967 * {@code keystore.type} security property, or the string 968 * {@literal "jks"} (acronym for {@literal "Java keystore"}) 969 * if no such property exists. 970 * 971 * <p>The default keystore type can be used by applications that do not 972 * want to use a hard-coded keystore type when calling one of the 973 * {@code getInstance} methods, and want to provide a default keystore 974 * type in case a user does not specify its own. 975 * 976 * <p>The default keystore type can be changed by setting the value of the 977 * {@code keystore.type} security property to the desired keystore type. 978 * 979 * @return the default keystore type as specified by the 980 * {@code keystore.type} security property, or the string {@literal "jks"} 981 * if no such property exists. 982 * @see java.security.Security security properties 983 */ 984 public static final String getDefaultType() { 985 String kstype; 986 kstype = AccessController.doPrivileged(new PrivilegedAction<>() { 987 public String run() { 988 return Security.getProperty(KEYSTORE_TYPE); 989 } 990 }); 991 if (kstype == null) { 992 kstype = "jks"; 993 } 994 return kstype; 995 } 996 997 /** 998 * Returns the provider of this keystore. 999 * 1000 * @return the provider of this keystore. 1001 */ 1002 public final Provider getProvider() 1003 { 1004 return this.provider; 1005 } 1006 1007 /** 1008 * Returns the type of this keystore. 1009 * 1010 * @return the type of this keystore. 1011 */ 1012 public final String getType() 1013 { 1014 return this.type; 1015 } 1016 1017 /** 1018 * Returns the key associated with the given alias, using the given 1019 * password to recover it. The key must have been associated with 1020 * the alias by a call to {@code setKeyEntry}, 1021 * or by a call to {@code setEntry} with a 1022 * {@code PrivateKeyEntry} or {@code SecretKeyEntry}. 1023 * 1024 * @param alias the alias name 1025 * @param password the password for recovering the key 1026 * 1027 * @return the requested key, or null if the given alias does not exist 1028 * or does not identify a key-related entry. 1029 * 1030 * @exception KeyStoreException if the keystore has not been initialized 1031 * (loaded). 1032 * @exception NoSuchAlgorithmException if the algorithm for recovering the 1033 * key cannot be found 1034 * @exception UnrecoverableKeyException if the key cannot be recovered 1035 * (e.g., the given password is wrong). 1036 */ 1037 public final Key getKey(String alias, char[] password) 1038 throws KeyStoreException, NoSuchAlgorithmException, 1039 UnrecoverableKeyException 1040 { 1041 if (!initialized) { 1042 throw new KeyStoreException("Uninitialized keystore"); 1043 } 1044 return keyStoreSpi.engineGetKey(alias, password); 1045 } 1046 1047 /** 1048 * Returns the certificate chain associated with the given alias. 1049 * The certificate chain must have been associated with the alias 1050 * by a call to {@code setKeyEntry}, 1051 * or by a call to {@code setEntry} with a 1052 * {@code PrivateKeyEntry}. 1053 * 1054 * @param alias the alias name 1055 * 1056 * @return the certificate chain (ordered with the user's certificate first 1057 * followed by zero or more certificate authorities), or null if the given alias 1058 * does not exist or does not contain a certificate chain 1059 * 1060 * @exception KeyStoreException if the keystore has not been initialized 1061 * (loaded). 1062 */ 1063 public final Certificate[] getCertificateChain(String alias) 1064 throws KeyStoreException 1065 { 1066 if (!initialized) { 1067 throw new KeyStoreException("Uninitialized keystore"); 1068 } 1069 return keyStoreSpi.engineGetCertificateChain(alias); 1070 } 1071 1072 /** 1073 * Returns the certificate associated with the given alias. 1074 * 1075 * <p> If the given alias name identifies an entry 1076 * created by a call to {@code setCertificateEntry}, 1077 * or created by a call to {@code setEntry} with a 1078 * {@code TrustedCertificateEntry}, 1079 * then the trusted certificate contained in that entry is returned. 1080 * 1081 * <p> If the given alias name identifies an entry 1082 * created by a call to {@code setKeyEntry}, 1083 * or created by a call to {@code setEntry} with a 1084 * {@code PrivateKeyEntry}, 1085 * then the first element of the certificate chain in that entry 1086 * is returned. 1087 * 1088 * @param alias the alias name 1089 * 1090 * @return the certificate, or null if the given alias does not exist or 1091 * does not contain a certificate. 1092 * 1093 * @exception KeyStoreException if the keystore has not been initialized 1094 * (loaded). 1095 */ 1096 public final Certificate getCertificate(String alias) 1097 throws KeyStoreException 1098 { 1099 if (!initialized) { 1100 throw new KeyStoreException("Uninitialized keystore"); 1101 } 1102 return keyStoreSpi.engineGetCertificate(alias); 1103 } 1104 1105 /** 1106 * Returns the creation date of the entry identified by the given alias. 1107 * 1108 * @param alias the alias name 1109 * 1110 * @return the creation date of this entry, or null if the given alias does 1111 * not exist 1112 * 1113 * @exception KeyStoreException if the keystore has not been initialized 1114 * (loaded). 1115 */ 1116 public final Date getCreationDate(String alias) 1117 throws KeyStoreException 1118 { 1119 if (!initialized) { 1120 throw new KeyStoreException("Uninitialized keystore"); 1121 } 1122 return keyStoreSpi.engineGetCreationDate(alias); 1123 } 1124 1125 /** 1126 * Assigns the given key to the given alias, protecting it with the given 1127 * password. 1128 * 1129 * <p>If the given key is of type {@code java.security.PrivateKey}, 1130 * it must be accompanied by a certificate chain certifying the 1131 * corresponding public key. 1132 * 1133 * <p>If the given alias already exists, the keystore information 1134 * associated with it is overridden by the given key (and possibly 1135 * certificate chain). 1136 * 1137 * @param alias the alias name 1138 * @param key the key to be associated with the alias 1139 * @param password the password to protect the key 1140 * @param chain the certificate chain for the corresponding public 1141 * key (only required if the given key is of type 1142 * {@code java.security.PrivateKey}). 1143 * 1144 * @exception KeyStoreException if the keystore has not been initialized 1145 * (loaded), the given key cannot be protected, or this operation fails 1146 * for some other reason 1147 */ 1148 public final void setKeyEntry(String alias, Key key, char[] password, 1149 Certificate[] chain) 1150 throws KeyStoreException 1151 { 1152 if (!initialized) { 1153 throw new KeyStoreException("Uninitialized keystore"); 1154 } 1155 if ((key instanceof PrivateKey) && 1156 (chain == null || chain.length == 0)) { 1157 throw new IllegalArgumentException("Private key must be " 1158 + "accompanied by certificate " 1159 + "chain"); 1160 } 1161 keyStoreSpi.engineSetKeyEntry(alias, key, password, chain); 1162 } 1163 1164 /** 1165 * Assigns the given key (that has already been protected) to the given 1166 * alias. 1167 * 1168 * <p>If the protected key is of type 1169 * {@code java.security.PrivateKey}, it must be accompanied by a 1170 * certificate chain certifying the corresponding public key. If the 1171 * underlying keystore implementation is of type {@code jks}, 1172 * {@code key} must be encoded as an 1173 * {@code EncryptedPrivateKeyInfo} as defined in the PKCS #8 standard. 1174 * 1175 * <p>If the given alias already exists, the keystore information 1176 * associated with it is overridden by the given key (and possibly 1177 * certificate chain). 1178 * 1179 * @param alias the alias name 1180 * @param key the key (in protected format) to be associated with the alias 1181 * @param chain the certificate chain for the corresponding public 1182 * key (only useful if the protected key is of type 1183 * {@code java.security.PrivateKey}). 1184 * 1185 * @exception KeyStoreException if the keystore has not been initialized 1186 * (loaded), or if this operation fails for some other reason. 1187 */ 1188 public final void setKeyEntry(String alias, byte[] key, 1189 Certificate[] chain) 1190 throws KeyStoreException 1191 { 1192 if (!initialized) { 1193 throw new KeyStoreException("Uninitialized keystore"); 1194 } 1195 keyStoreSpi.engineSetKeyEntry(alias, key, chain); 1196 } 1197 1198 /** 1199 * Assigns the given trusted certificate to the given alias. 1200 * 1201 * <p> If the given alias identifies an existing entry 1202 * created by a call to {@code setCertificateEntry}, 1203 * or created by a call to {@code setEntry} with a 1204 * {@code TrustedCertificateEntry}, 1205 * the trusted certificate in the existing entry 1206 * is overridden by the given certificate. 1207 * 1208 * @param alias the alias name 1209 * @param cert the certificate 1210 * 1211 * @exception KeyStoreException if the keystore has not been initialized, 1212 * or the given alias already exists and does not identify an 1213 * entry containing a trusted certificate, 1214 * or this operation fails for some other reason. 1215 */ 1216 public final void setCertificateEntry(String alias, Certificate cert) 1217 throws KeyStoreException 1218 { 1219 if (!initialized) { 1220 throw new KeyStoreException("Uninitialized keystore"); 1221 } 1222 keyStoreSpi.engineSetCertificateEntry(alias, cert); 1223 } 1224 1225 /** 1226 * Deletes the entry identified by the given alias from this keystore. 1227 * 1228 * @param alias the alias name 1229 * 1230 * @exception KeyStoreException if the keystore has not been initialized, 1231 * or if the entry cannot be removed. 1232 */ 1233 public final void deleteEntry(String alias) 1234 throws KeyStoreException 1235 { 1236 if (!initialized) { 1237 throw new KeyStoreException("Uninitialized keystore"); 1238 } 1239 keyStoreSpi.engineDeleteEntry(alias); 1240 } 1241 1242 /** 1243 * Lists all the alias names of this keystore. 1244 * 1245 * @return enumeration of the alias names 1246 * 1247 * @exception KeyStoreException if the keystore has not been initialized 1248 * (loaded). 1249 */ 1250 public final Enumeration<String> aliases() 1251 throws KeyStoreException 1252 { 1253 if (!initialized) { 1254 throw new KeyStoreException("Uninitialized keystore"); 1255 } 1256 return keyStoreSpi.engineAliases(); 1257 } 1258 1259 /** 1260 * Checks if the given alias exists in this keystore. 1261 * 1262 * @param alias the alias name 1263 * 1264 * @return true if the alias exists, false otherwise 1265 * 1266 * @exception KeyStoreException if the keystore has not been initialized 1267 * (loaded). 1268 */ 1269 public final boolean containsAlias(String alias) 1270 throws KeyStoreException 1271 { 1272 if (!initialized) { 1273 throw new KeyStoreException("Uninitialized keystore"); 1274 } 1275 return keyStoreSpi.engineContainsAlias(alias); 1276 } 1277 1278 /** 1279 * Retrieves the number of entries in this keystore. 1280 * 1281 * @return the number of entries in this keystore 1282 * 1283 * @exception KeyStoreException if the keystore has not been initialized 1284 * (loaded). 1285 */ 1286 public final int size() 1287 throws KeyStoreException 1288 { 1289 if (!initialized) { 1290 throw new KeyStoreException("Uninitialized keystore"); 1291 } 1292 return keyStoreSpi.engineSize(); 1293 } 1294 1295 /** 1296 * Returns true if the entry identified by the given alias 1297 * was created by a call to {@code setKeyEntry}, 1298 * or created by a call to {@code setEntry} with a 1299 * {@code PrivateKeyEntry} or a {@code SecretKeyEntry}. 1300 * 1301 * @param alias the alias for the keystore entry to be checked 1302 * 1303 * @return true if the entry identified by the given alias is a 1304 * key-related entry, false otherwise. 1305 * 1306 * @exception KeyStoreException if the keystore has not been initialized 1307 * (loaded). 1308 */ 1309 public final boolean isKeyEntry(String alias) 1310 throws KeyStoreException 1311 { 1312 if (!initialized) { 1313 throw new KeyStoreException("Uninitialized keystore"); 1314 } 1315 return keyStoreSpi.engineIsKeyEntry(alias); 1316 } 1317 1318 /** 1319 * Returns true if the entry identified by the given alias 1320 * was created by a call to {@code setCertificateEntry}, 1321 * or created by a call to {@code setEntry} with a 1322 * {@code TrustedCertificateEntry}. 1323 * 1324 * @param alias the alias for the keystore entry to be checked 1325 * 1326 * @return true if the entry identified by the given alias contains a 1327 * trusted certificate, false otherwise. 1328 * 1329 * @exception KeyStoreException if the keystore has not been initialized 1330 * (loaded). 1331 */ 1332 public final boolean isCertificateEntry(String alias) 1333 throws KeyStoreException 1334 { 1335 if (!initialized) { 1336 throw new KeyStoreException("Uninitialized keystore"); 1337 } 1338 return keyStoreSpi.engineIsCertificateEntry(alias); 1339 } 1340 1341 /** 1342 * Returns the (alias) name of the first keystore entry whose certificate 1343 * matches the given certificate. 1344 * 1345 * <p> This method attempts to match the given certificate with each 1346 * keystore entry. If the entry being considered was 1347 * created by a call to {@code setCertificateEntry}, 1348 * or created by a call to {@code setEntry} with a 1349 * {@code TrustedCertificateEntry}, 1350 * then the given certificate is compared to that entry's certificate. 1351 * 1352 * <p> If the entry being considered was 1353 * created by a call to {@code setKeyEntry}, 1354 * or created by a call to {@code setEntry} with a 1355 * {@code PrivateKeyEntry}, 1356 * then the given certificate is compared to the first 1357 * element of that entry's certificate chain. 1358 * 1359 * @param cert the certificate to match with. 1360 * 1361 * @return the alias name of the first entry with a matching certificate, 1362 * or null if no such entry exists in this keystore. 1363 * 1364 * @exception KeyStoreException if the keystore has not been initialized 1365 * (loaded). 1366 */ 1367 public final String getCertificateAlias(Certificate cert) 1368 throws KeyStoreException 1369 { 1370 if (!initialized) { 1371 throw new KeyStoreException("Uninitialized keystore"); 1372 } 1373 return keyStoreSpi.engineGetCertificateAlias(cert); 1374 } 1375 1376 /** 1377 * Stores this keystore to the given output stream, and protects its 1378 * integrity with the given password. 1379 * 1380 * @param stream the output stream to which this keystore is written. 1381 * @param password the password to generate the keystore integrity check 1382 * 1383 * @exception KeyStoreException if the keystore has not been initialized 1384 * (loaded). 1385 * @exception IOException if there was an I/O problem with data 1386 * @exception NoSuchAlgorithmException if the appropriate data integrity 1387 * algorithm could not be found 1388 * @exception CertificateException if any of the certificates included in 1389 * the keystore data could not be stored 1390 */ 1391 public final void store(OutputStream stream, char[] password) 1392 throws KeyStoreException, IOException, NoSuchAlgorithmException, 1393 CertificateException 1394 { 1395 if (!initialized) { 1396 throw new KeyStoreException("Uninitialized keystore"); 1397 } 1398 keyStoreSpi.engineStore(stream, password); 1399 } 1400 1401 /** 1402 * Stores this keystore using the given {@code LoadStoreParameter}. 1403 * 1404 * @param param the {@code LoadStoreParameter} 1405 * that specifies how to store the keystore, 1406 * which may be {@code null} 1407 * 1408 * @exception IllegalArgumentException if the given 1409 * {@code LoadStoreParameter} 1410 * input is not recognized 1411 * @exception KeyStoreException if the keystore has not been initialized 1412 * (loaded) 1413 * @exception IOException if there was an I/O problem with data 1414 * @exception NoSuchAlgorithmException if the appropriate data integrity 1415 * algorithm could not be found 1416 * @exception CertificateException if any of the certificates included in 1417 * the keystore data could not be stored 1418 * 1419 * @since 1.5 1420 */ 1421 public final void store(LoadStoreParameter param) 1422 throws KeyStoreException, IOException, 1423 NoSuchAlgorithmException, CertificateException { 1424 if (!initialized) { 1425 throw new KeyStoreException("Uninitialized keystore"); 1426 } 1427 keyStoreSpi.engineStore(param); 1428 } 1429 1430 /** 1431 * Loads this KeyStore from the given input stream. 1432 * 1433 * <p>A password may be given to unlock the keystore 1434 * (e.g. the keystore resides on a hardware token device), 1435 * or to check the integrity of the keystore data. 1436 * If a password is not given for integrity checking, 1437 * then integrity checking is not performed. 1438 * 1439 * <p>In order to create an empty keystore, or if the keystore cannot 1440 * be initialized from a stream, pass {@code null} 1441 * as the {@code stream} argument. 1442 * 1443 * <p> Note that if this keystore has already been loaded, it is 1444 * reinitialized and loaded again from the given input stream. 1445 * 1446 * @param stream the input stream from which the keystore is loaded, 1447 * or {@code null} 1448 * @param password the password used to check the integrity of 1449 * the keystore, the password used to unlock the keystore, 1450 * or {@code null} 1451 * 1452 * @exception IOException if there is an I/O or format problem with the 1453 * keystore data, if a password is required but not given, 1454 * or if the given password was incorrect. If the error is due to a 1455 * wrong password, the {@link Throwable#getCause cause} of the 1456 * {@code IOException} should be an 1457 * {@code UnrecoverableKeyException} 1458 * @exception NoSuchAlgorithmException if the algorithm used to check 1459 * the integrity of the keystore cannot be found 1460 * @exception CertificateException if any of the certificates in the 1461 * keystore could not be loaded 1462 */ 1463 public final void load(InputStream stream, char[] password) 1464 throws IOException, NoSuchAlgorithmException, CertificateException 1465 { 1466 keyStoreSpi.engineLoad(stream, password); 1467 initialized = true; 1468 } 1469 1470 /** 1471 * Loads this keystore using the given {@code LoadStoreParameter}. 1472 * 1473 * <p> Note that if this KeyStore has already been loaded, it is 1474 * reinitialized and loaded again from the given parameter. 1475 * 1476 * @param param the {@code LoadStoreParameter} 1477 * that specifies how to load the keystore, 1478 * which may be {@code null} 1479 * 1480 * @exception IllegalArgumentException if the given 1481 * {@code LoadStoreParameter} 1482 * input is not recognized 1483 * @exception IOException if there is an I/O or format problem with the 1484 * keystore data. If the error is due to an incorrect 1485 * {@code ProtectionParameter} (e.g. wrong password) 1486 * the {@link Throwable#getCause cause} of the 1487 * {@code IOException} should be an 1488 * {@code UnrecoverableKeyException} 1489 * @exception NoSuchAlgorithmException if the algorithm used to check 1490 * the integrity of the keystore cannot be found 1491 * @exception CertificateException if any of the certificates in the 1492 * keystore could not be loaded 1493 * 1494 * @since 1.5 1495 */ 1496 public final void load(LoadStoreParameter param) 1497 throws IOException, NoSuchAlgorithmException, 1498 CertificateException { 1499 1500 keyStoreSpi.engineLoad(param); 1501 initialized = true; 1502 } 1503 1504 /** 1505 * Gets a keystore {@code Entry} for the specified alias 1506 * with the specified protection parameter. 1507 * 1508 * @param alias get the keystore {@code Entry} for this alias 1509 * @param protParam the {@code ProtectionParameter} 1510 * used to protect the {@code Entry}, 1511 * which may be {@code null} 1512 * 1513 * @return the keystore {@code Entry} for the specified alias, 1514 * or {@code null} if there is no such entry 1515 * 1516 * @exception NullPointerException if 1517 * {@code alias} is {@code null} 1518 * @exception NoSuchAlgorithmException if the algorithm for recovering the 1519 * entry cannot be found 1520 * @exception UnrecoverableEntryException if the specified 1521 * {@code protParam} were insufficient or invalid 1522 * @exception UnrecoverableKeyException if the entry is a 1523 * {@code PrivateKeyEntry} or {@code SecretKeyEntry} 1524 * and the specified {@code protParam} does not contain 1525 * the information needed to recover the key (e.g. wrong password) 1526 * @exception KeyStoreException if the keystore has not been initialized 1527 * (loaded). 1528 * @see #setEntry(String, KeyStore.Entry, KeyStore.ProtectionParameter) 1529 * 1530 * @since 1.5 1531 */ 1532 public final Entry getEntry(String alias, ProtectionParameter protParam) 1533 throws NoSuchAlgorithmException, UnrecoverableEntryException, 1534 KeyStoreException { 1535 1536 if (alias == null) { 1537 throw new NullPointerException("invalid null input"); 1538 } 1539 if (!initialized) { 1540 throw new KeyStoreException("Uninitialized keystore"); 1541 } 1542 return keyStoreSpi.engineGetEntry(alias, protParam); 1543 } 1544 1545 /** 1546 * Saves a keystore {@code Entry} under the specified alias. 1547 * The protection parameter is used to protect the 1548 * {@code Entry}. 1549 * 1550 * <p> If an entry already exists for the specified alias, 1551 * it is overridden. 1552 * 1553 * @param alias save the keystore {@code Entry} under this alias 1554 * @param entry the {@code Entry} to save 1555 * @param protParam the {@code ProtectionParameter} 1556 * used to protect the {@code Entry}, 1557 * which may be {@code null} 1558 * 1559 * @exception NullPointerException if 1560 * {@code alias} or {@code entry} 1561 * is {@code null} 1562 * @exception KeyStoreException if the keystore has not been initialized 1563 * (loaded), or if this operation fails for some other reason 1564 * 1565 * @see #getEntry(String, KeyStore.ProtectionParameter) 1566 * 1567 * @since 1.5 1568 */ 1569 public final void setEntry(String alias, Entry entry, 1570 ProtectionParameter protParam) 1571 throws KeyStoreException { 1572 if (alias == null || entry == null) { 1573 throw new NullPointerException("invalid null input"); 1574 } 1575 if (!initialized) { 1576 throw new KeyStoreException("Uninitialized keystore"); 1577 } 1578 keyStoreSpi.engineSetEntry(alias, entry, protParam); 1579 } 1580 1581 /** 1582 * Determines if the keystore {@code Entry} for the specified 1583 * {@code alias} is an instance or subclass of the specified 1584 * {@code entryClass}. 1585 * 1586 * @param alias the alias name 1587 * @param entryClass the entry class 1588 * 1589 * @return true if the keystore {@code Entry} for the specified 1590 * {@code alias} is an instance or subclass of the 1591 * specified {@code entryClass}, false otherwise 1592 * 1593 * @exception NullPointerException if 1594 * {@code alias} or {@code entryClass} 1595 * is {@code null} 1596 * @exception KeyStoreException if the keystore has not been 1597 * initialized (loaded) 1598 * 1599 * @since 1.5 1600 */ 1601 public final boolean 1602 entryInstanceOf(String alias, 1603 Class<? extends KeyStore.Entry> entryClass) 1604 throws KeyStoreException 1605 { 1606 1607 if (alias == null || entryClass == null) { 1608 throw new NullPointerException("invalid null input"); 1609 } 1610 if (!initialized) { 1611 throw new KeyStoreException("Uninitialized keystore"); 1612 } 1613 return keyStoreSpi.engineEntryInstanceOf(alias, entryClass); 1614 } 1615 1616 /** 1617 * Returns a loaded keystore object of the appropriate keystore type. 1618 * First the keystore type is determined by probing the specified file. 1619 * Then a keystore object is instantiated and loaded using the data from 1620 * that file. 1621 * 1622 * <p> 1623 * A password may be given to unlock the keystore 1624 * (e.g. the keystore resides on a hardware token device), 1625 * or to check the integrity of the keystore data. 1626 * If a password is not given for integrity checking, 1627 * then integrity checking is not performed. 1628 * 1629 * <p> 1630 * This method traverses the list of registered security 1631 * {@linkplain Provider providers}, starting with the most 1632 * preferred Provider. 1633 * For each {@link KeyStoreSpi} implementation supported by a 1634 * Provider, it invokes the {@link 1635 * KeyStoreSpi#engineProbe(InputStream) engineProbe} method to 1636 * determine if it supports the specified keystore. 1637 * A new KeyStore object is returned that encapsulates the KeyStoreSpi 1638 * implementation from the first Provider that supports the specified file. 1639 * 1640 * <p> Note that the list of registered providers may be retrieved via 1641 * the {@link Security#getProviders() Security.getProviders()} method. 1642 * 1643 * @param file the keystore file 1644 * @param password the keystore password, which may be {@code null} 1645 * 1646 * @return a keystore object loaded with keystore data 1647 * 1648 * @throws KeyStoreException if no Provider supports a KeyStoreSpi 1649 * implementation for the specified keystore file. 1650 * @throws IOException if there is an I/O or format problem with the 1651 * keystore data, if a password is required but not given, 1652 * or if the given password was incorrect. If the error is 1653 * due to a wrong password, the {@link Throwable#getCause cause} 1654 * of the {@code IOException} should be an 1655 * {@code UnrecoverableKeyException}. 1656 * @throws NoSuchAlgorithmException if the algorithm used to check the 1657 * integrity of the keystore cannot be found. 1658 * @throws CertificateException if any of the certificates in the 1659 * keystore could not be loaded. 1660 * @throws IllegalArgumentException if file does not exist or does not 1661 * refer to a normal file. 1662 * @throws NullPointerException if file is {@code null}. 1663 * @throws SecurityException if a security manager exists and its 1664 * {@link java.lang.SecurityManager#checkRead} method denies 1665 * read access to the specified file. 1666 * 1667 * @see Provider 1668 * 1669 * @since 1.9 1670 */ 1671 public static final KeyStore getInstance(File file, char[] password) 1672 throws KeyStoreException, IOException, NoSuchAlgorithmException, 1673 CertificateException { 1674 return getInstance(file, password, null, true); 1675 } 1676 1677 /** 1678 * Returns a loaded keystore object of the appropriate keystore type. 1679 * First the keystore type is determined by probing the specified file. 1680 * Then a keystore object is instantiated and loaded using the data from 1681 * that file. 1682 * A {@code LoadStoreParameter} may be supplied which specifies how to 1683 * unlock the keystore data or perform an integrity check. 1684 * 1685 * <p> 1686 * This method traverses the list of registered security {@linkplain 1687 * Provider providers}, starting with the most preferred Provider. 1688 * For each {@link KeyStoreSpi} implementation supported by a 1689 * Provider, it invokes the {@link 1690 * KeyStoreSpi#engineProbe(InputStream) engineProbe} method to 1691 * determine if it supports the specified keystore. 1692 * A new KeyStore object is returned that encapsulates the KeyStoreSpi 1693 * implementation from the first Provider that supports the specified file. 1694 * 1695 * <p> Note that the list of registered providers may be retrieved via 1696 * the {@link Security#getProviders() Security.getProviders()} method. 1697 * 1698 * @param file the keystore file 1699 * @param param the {@code LoadStoreParameter} that specifies how to load 1700 * the keystore, which may be {@code null} 1701 * 1702 * @return a keystore object loaded with keystore data 1703 * 1704 * @throws KeyStoreException if no Provider supports a KeyStoreSpi 1705 * implementation for the specified keystore file. 1706 * @throws IOException if there is an I/O or format problem with the 1707 * keystore data. If the error is due to an incorrect 1708 * {@code ProtectionParameter} (e.g. wrong password) 1709 * the {@link Throwable#getCause cause} of the 1710 * {@code IOException} should be an 1711 * {@code UnrecoverableKeyException}. 1712 * @throws NoSuchAlgorithmException if the algorithm used to check the 1713 * integrity of the keystore cannot be found. 1714 * @throws CertificateException if any of the certificates in the 1715 * keystore could not be loaded. 1716 * @throws IllegalArgumentException if file does not exist or does not 1717 * refer to a normal file, or if param is not recognized. 1718 * @throws NullPointerException if file is {@code null}. 1719 * @throws SecurityException if a security manager exists and its 1720 * {@link java.lang.SecurityManager#checkRead} method denies 1721 * read access to the specified file. 1722 * 1723 * @see Provider 1724 * 1725 * @since 1.9 1726 */ 1727 public static final KeyStore getInstance(File file, 1728 LoadStoreParameter param) throws KeyStoreException, IOException, 1729 NoSuchAlgorithmException, CertificateException { 1730 return getInstance(file, null, param, false); 1731 } 1732 1733 // Used by getInstance(File, char[]) & getInstance(File, LoadStoreParameter) 1734 private static final KeyStore getInstance(File file, char[] password, 1735 LoadStoreParameter param, boolean hasPassword) 1736 throws KeyStoreException, IOException, NoSuchAlgorithmException, 1737 CertificateException { 1738 1739 if (file == null) { 1740 throw new NullPointerException(); 1741 } 1742 1743 if (file.isFile() == false) { 1744 throw new IllegalArgumentException( 1745 "File does not exist or it does not refer to a normal file: " + 1746 file); 1747 } 1748 1749 KeyStore keystore = null; 1750 1751 try (DataInputStream dataStream = 1752 new DataInputStream( 1753 new BufferedInputStream( 1754 new FileInputStream(file)))) { 1755 1756 dataStream.mark(Integer.MAX_VALUE); 1757 1758 // Detect the keystore type 1759 for (String type : Security.getAlgorithms("KeyStore")) { 1760 Object[] objs = null; 1761 1762 try { 1763 objs = Security.getImpl(type, "KeyStore", (String)null); 1764 1765 KeyStoreSpi impl = (KeyStoreSpi)objs[0]; 1766 if (impl.engineProbe(dataStream)) { 1767 1768 if (kdebug != null) { 1769 kdebug.println(type + " keystore detected: " + 1770 file); 1771 } 1772 1773 keystore = new KeyStore(impl, (Provider)objs[1], type); 1774 break; 1775 } 1776 } catch (NoSuchAlgorithmException | NoSuchProviderException e) { 1777 // ignore 1778 if (kdebug != null) { 1779 kdebug.println(type + " not found - " + e); 1780 } 1781 } catch (IOException e) { 1782 // ignore 1783 if (kdebug != null) { 1784 kdebug.println("I/O error in " + file + " - " + e); 1785 } 1786 } 1787 dataStream.reset(); // prepare the stream for the next probe 1788 } 1789 1790 // Load the keystore data 1791 if (keystore != null) { 1792 if (hasPassword) { 1793 dataStream.reset(); // prepare the stream for loading 1794 keystore.load(dataStream, password); 1795 } else { 1796 keystore.load(param); 1797 } 1798 return keystore; 1799 } 1800 } 1801 1802 throw new KeyStoreException("Unrecognized keystore format: " + 1803 keystore); 1804 } 1805 1806 /** 1807 * A description of a to-be-instantiated KeyStore object. 1808 * 1809 * <p>An instance of this class encapsulates the information needed to 1810 * instantiate and initialize a KeyStore object. That process is 1811 * triggered when the {@linkplain #getKeyStore} method is called. 1812 * 1813 * <p>This makes it possible to decouple configuration from KeyStore 1814 * object creation and e.g. delay a password prompt until it is 1815 * needed. 1816 * 1817 * @see KeyStore 1818 * @see javax.net.ssl.KeyStoreBuilderParameters 1819 * @since 1.5 1820 */ 1821 public abstract static class Builder { 1822 1823 // maximum times to try the callbackhandler if the password is wrong 1824 static final int MAX_CALLBACK_TRIES = 3; 1825 1826 /** 1827 * Construct a new Builder. 1828 */ 1829 protected Builder() { 1830 // empty 1831 } 1832 1833 /** 1834 * Returns the KeyStore described by this object. 1835 * 1836 * @return the {@code KeyStore} described by this object 1837 * @exception KeyStoreException if an error occurred during the 1838 * operation, for example if the KeyStore could not be 1839 * instantiated or loaded 1840 */ 1841 public abstract KeyStore getKeyStore() throws KeyStoreException; 1842 1843 /** 1844 * Returns the ProtectionParameters that should be used to obtain 1845 * the {@link KeyStore.Entry Entry} with the given alias. 1846 * The {@code getKeyStore} method must be invoked before this 1847 * method may be called. 1848 * 1849 * @return the ProtectionParameters that should be used to obtain 1850 * the {@link KeyStore.Entry Entry} with the given alias. 1851 * @param alias the alias of the KeyStore entry 1852 * @throws NullPointerException if alias is null 1853 * @throws KeyStoreException if an error occurred during the 1854 * operation 1855 * @throws IllegalStateException if the getKeyStore method has 1856 * not been invoked prior to calling this method 1857 */ 1858 public abstract ProtectionParameter getProtectionParameter(String alias) 1859 throws KeyStoreException; 1860 1861 /** 1862 * Returns a new Builder that encapsulates the given KeyStore. 1863 * The {@linkplain #getKeyStore} method of the returned object 1864 * will return {@code keyStore}, the {@linkplain 1865 * #getProtectionParameter getProtectionParameter()} method will 1866 * return {@code protectionParameters}. 1867 * 1868 * <p> This is useful if an existing KeyStore object needs to be 1869 * used with Builder-based APIs. 1870 * 1871 * @return a new Builder object 1872 * @param keyStore the KeyStore to be encapsulated 1873 * @param protectionParameter the ProtectionParameter used to 1874 * protect the KeyStore entries 1875 * @throws NullPointerException if keyStore or 1876 * protectionParameters is null 1877 * @throws IllegalArgumentException if the keyStore has not been 1878 * initialized 1879 */ 1880 public static Builder newInstance(final KeyStore keyStore, 1881 final ProtectionParameter protectionParameter) { 1882 if ((keyStore == null) || (protectionParameter == null)) { 1883 throw new NullPointerException(); 1884 } 1885 if (keyStore.initialized == false) { 1886 throw new IllegalArgumentException("KeyStore not initialized"); 1887 } 1888 return new Builder() { 1889 private volatile boolean getCalled; 1890 1891 public KeyStore getKeyStore() { 1892 getCalled = true; 1893 return keyStore; 1894 } 1895 1896 public ProtectionParameter getProtectionParameter(String alias) 1897 { 1898 if (alias == null) { 1899 throw new NullPointerException(); 1900 } 1901 if (getCalled == false) { 1902 throw new IllegalStateException 1903 ("getKeyStore() must be called first"); 1904 } 1905 return protectionParameter; 1906 } 1907 }; 1908 } 1909 1910 /** 1911 * Returns a new Builder object. 1912 * 1913 * <p>The first call to the {@link #getKeyStore} method on the returned 1914 * builder will create a KeyStore of type {@code type} and call 1915 * its {@link KeyStore#load load()} method. 1916 * The {@code inputStream} argument is constructed from 1917 * {@code file}. 1918 * If {@code protection} is a 1919 * {@code PasswordProtection}, the password is obtained by 1920 * calling the {@code getPassword} method. 1921 * Otherwise, if {@code protection} is a 1922 * {@code CallbackHandlerProtection}, the password is obtained 1923 * by invoking the CallbackHandler. 1924 * 1925 * <p>Subsequent calls to {@link #getKeyStore} return the same object 1926 * as the initial call. If the initial call failed with a 1927 * KeyStoreException, subsequent calls also throw a 1928 * KeyStoreException. 1929 * 1930 * <p>The KeyStore is instantiated from {@code provider} if 1931 * non-null. Otherwise, all installed providers are searched. 1932 * 1933 * <p>Calls to {@link #getProtectionParameter getProtectionParameter()} 1934 * will return a {@link KeyStore.PasswordProtection PasswordProtection} 1935 * object encapsulating the password that was used to invoke the 1936 * {@code load} method. 1937 * 1938 * <p><em>Note</em> that the {@link #getKeyStore} method is executed 1939 * within the {@link AccessControlContext} of the code invoking this 1940 * method. 1941 * 1942 * @return a new Builder object 1943 * @param type the type of KeyStore to be constructed 1944 * @param provider the provider from which the KeyStore is to 1945 * be instantiated (or null) 1946 * @param file the File that contains the KeyStore data 1947 * @param protection the ProtectionParameter securing the KeyStore data 1948 * @throws NullPointerException if type, file or protection is null 1949 * @throws IllegalArgumentException if protection is not an instance 1950 * of either PasswordProtection or CallbackHandlerProtection; or 1951 * if file does not exist or does not refer to a normal file 1952 */ 1953 public static Builder newInstance(String type, Provider provider, 1954 File file, ProtectionParameter protection) { 1955 if ((type == null) || (file == null) || (protection == null)) { 1956 throw new NullPointerException(); 1957 } 1958 if ((protection instanceof PasswordProtection == false) && 1959 (protection instanceof CallbackHandlerProtection == false)) { 1960 throw new IllegalArgumentException 1961 ("Protection must be PasswordProtection or " + 1962 "CallbackHandlerProtection"); 1963 } 1964 if (file.isFile() == false) { 1965 throw new IllegalArgumentException 1966 ("File does not exist or it does not refer " + 1967 "to a normal file: " + file); 1968 } 1969 return new FileBuilder(type, provider, file, protection, 1970 AccessController.getContext()); 1971 } 1972 1973 /** 1974 * Returns a new Builder object. 1975 * 1976 * <p>The first call to the {@link #getKeyStore} method on the returned 1977 * builder will create a KeyStore using {@code file} to detect the 1978 * keystore type and then call its {@link KeyStore#load load()} method. 1979 * It uses the same algorithm to determine the keystore type as 1980 * described in {@link KeyStore#getInstance(File, LoadStoreParameter)}. 1981 * The {@code inputStream} argument is constructed from {@code file}. 1982 * If {@code protection} is a {@code PasswordProtection}, the password 1983 * is obtained by calling the {@code getPassword} method. 1984 * Otherwise, if {@code protection} is a 1985 * {@code CallbackHandlerProtection}, 1986 * the password is obtained by invoking the CallbackHandler. 1987 * 1988 * <p>Subsequent calls to {@link #getKeyStore} return the same object 1989 * as the initial call. If the initial call failed with a 1990 * KeyStoreException, subsequent calls also throw a KeyStoreException. 1991 * 1992 * <p>Calls to {@link #getProtectionParameter getProtectionParameter()} 1993 * will return a {@link KeyStore.PasswordProtection PasswordProtection} 1994 * object encapsulating the password that was used to invoke the 1995 * {@code load} method. 1996 * 1997 * <p><em>Note</em> that the {@link #getKeyStore} method is executed 1998 * within the {@link AccessControlContext} of the code invoking this 1999 * method. 2000 * 2001 * @return a new Builder object 2002 * @param file the File that contains the KeyStore data 2003 * @param protection the ProtectionParameter securing the KeyStore data 2004 * @throws NullPointerException if file or protection is null 2005 * @throws IllegalArgumentException if protection is not an instance 2006 * of either PasswordProtection or CallbackHandlerProtection; or 2007 * if file does not exist or does not refer to a normal file 2008 * 2009 * @since 1.9 2010 */ 2011 public static Builder newInstance(File file, 2012 ProtectionParameter protection) { 2013 2014 return newInstance("", null, file, protection); 2015 } 2016 2017 private static final class FileBuilder extends Builder { 2018 2019 private final String type; 2020 private final Provider provider; 2021 private final File file; 2022 private ProtectionParameter protection; 2023 private ProtectionParameter keyProtection; 2024 private final AccessControlContext context; 2025 2026 private KeyStore keyStore; 2027 2028 private Throwable oldException; 2029 2030 FileBuilder(String type, Provider provider, File file, 2031 ProtectionParameter protection, 2032 AccessControlContext context) { 2033 this.type = type; 2034 this.provider = provider; 2035 this.file = file; 2036 this.protection = protection; 2037 this.context = context; 2038 } 2039 2040 public synchronized KeyStore getKeyStore() throws KeyStoreException 2041 { 2042 if (keyStore != null) { 2043 return keyStore; 2044 } 2045 if (oldException != null) { 2046 throw new KeyStoreException 2047 ("Previous KeyStore instantiation failed", 2048 oldException); 2049 } 2050 PrivilegedExceptionAction<KeyStore> action = 2051 new PrivilegedExceptionAction<KeyStore>() { 2052 public KeyStore run() throws Exception { 2053 if (protection instanceof CallbackHandlerProtection == false) { 2054 return run0(); 2055 } 2056 // when using a CallbackHandler, 2057 // reprompt if the password is wrong 2058 int tries = 0; 2059 while (true) { 2060 tries++; 2061 try { 2062 return run0(); 2063 } catch (IOException e) { 2064 if ((tries < MAX_CALLBACK_TRIES) 2065 && (e.getCause() instanceof UnrecoverableKeyException)) { 2066 continue; 2067 } 2068 throw e; 2069 } 2070 } 2071 } 2072 public KeyStore run0() throws Exception { 2073 KeyStore ks; 2074 char[] password = null; 2075 2076 // Acquire keystore password 2077 if (protection instanceof PasswordProtection) { 2078 password = 2079 ((PasswordProtection)protection).getPassword(); 2080 keyProtection = protection; 2081 } else { 2082 CallbackHandler handler = 2083 ((CallbackHandlerProtection)protection) 2084 .getCallbackHandler(); 2085 PasswordCallback callback = new PasswordCallback 2086 ("Password for keystore " + file.getName(), 2087 false); 2088 handler.handle(new Callback[] {callback}); 2089 password = callback.getPassword(); 2090 if (password == null) { 2091 throw new KeyStoreException("No password" + 2092 " provided"); 2093 } 2094 callback.clearPassword(); 2095 keyProtection = new PasswordProtection(password); 2096 } 2097 2098 if (type.isEmpty()) { 2099 // Instantiate keystore and load keystore data 2100 ks = KeyStore.getInstance(file, password); 2101 } else { 2102 // Instantiate keystore 2103 if (provider == null) { 2104 ks = KeyStore.getInstance(type); 2105 } else { 2106 ks = KeyStore.getInstance(type, provider); 2107 } 2108 // Load keystore data 2109 try (InputStream in = new FileInputStream(file)) { 2110 ks.load(in, password); 2111 } 2112 } 2113 return ks; 2114 } 2115 }; 2116 try { 2117 keyStore = AccessController.doPrivileged(action, context); 2118 return keyStore; 2119 } catch (PrivilegedActionException e) { 2120 oldException = e.getCause(); 2121 throw new KeyStoreException 2122 ("KeyStore instantiation failed", oldException); 2123 } 2124 } 2125 2126 public synchronized ProtectionParameter 2127 getProtectionParameter(String alias) { 2128 if (alias == null) { 2129 throw new NullPointerException(); 2130 } 2131 if (keyStore == null) { 2132 throw new IllegalStateException 2133 ("getKeyStore() must be called first"); 2134 } 2135 return keyProtection; 2136 } 2137 } 2138 2139 /** 2140 * Returns a new Builder object. 2141 * 2142 * <p>Each call to the {@link #getKeyStore} method on the returned 2143 * builder will return a new KeyStore object of type {@code type}. 2144 * Its {@link KeyStore#load(KeyStore.LoadStoreParameter) load()} 2145 * method is invoked using a 2146 * {@code LoadStoreParameter} that encapsulates 2147 * {@code protection}. 2148 * 2149 * <p>The KeyStore is instantiated from {@code provider} if 2150 * non-null. Otherwise, all installed providers are searched. 2151 * 2152 * <p>Calls to {@link #getProtectionParameter getProtectionParameter()} 2153 * will return {@code protection}. 2154 * 2155 * <p><em>Note</em> that the {@link #getKeyStore} method is executed 2156 * within the {@link AccessControlContext} of the code invoking this 2157 * method. 2158 * 2159 * @return a new Builder object 2160 * @param type the type of KeyStore to be constructed 2161 * @param provider the provider from which the KeyStore is to 2162 * be instantiated (or null) 2163 * @param protection the ProtectionParameter securing the Keystore 2164 * @throws NullPointerException if type or protection is null 2165 */ 2166 public static Builder newInstance(final String type, 2167 final Provider provider, final ProtectionParameter protection) { 2168 if ((type == null) || (protection == null)) { 2169 throw new NullPointerException(); 2170 } 2171 final AccessControlContext context = AccessController.getContext(); 2172 return new Builder() { 2173 private volatile boolean getCalled; 2174 private IOException oldException; 2175 2176 private final PrivilegedExceptionAction<KeyStore> action 2177 = new PrivilegedExceptionAction<KeyStore>() { 2178 2179 public KeyStore run() throws Exception { 2180 KeyStore ks; 2181 if (provider == null) { 2182 ks = KeyStore.getInstance(type); 2183 } else { 2184 ks = KeyStore.getInstance(type, provider); 2185 } 2186 LoadStoreParameter param = new SimpleLoadStoreParameter(protection); 2187 if (protection instanceof CallbackHandlerProtection == false) { 2188 ks.load(param); 2189 } else { 2190 // when using a CallbackHandler, 2191 // reprompt if the password is wrong 2192 int tries = 0; 2193 while (true) { 2194 tries++; 2195 try { 2196 ks.load(param); 2197 break; 2198 } catch (IOException e) { 2199 if (e.getCause() instanceof UnrecoverableKeyException) { 2200 if (tries < MAX_CALLBACK_TRIES) { 2201 continue; 2202 } else { 2203 oldException = e; 2204 } 2205 } 2206 throw e; 2207 } 2208 } 2209 } 2210 getCalled = true; 2211 return ks; 2212 } 2213 }; 2214 2215 public synchronized KeyStore getKeyStore() 2216 throws KeyStoreException { 2217 if (oldException != null) { 2218 throw new KeyStoreException 2219 ("Previous KeyStore instantiation failed", 2220 oldException); 2221 } 2222 try { 2223 return AccessController.doPrivileged(action, context); 2224 } catch (PrivilegedActionException e) { 2225 Throwable cause = e.getCause(); 2226 throw new KeyStoreException 2227 ("KeyStore instantiation failed", cause); 2228 } 2229 } 2230 2231 public ProtectionParameter getProtectionParameter(String alias) 2232 { 2233 if (alias == null) { 2234 throw new NullPointerException(); 2235 } 2236 if (getCalled == false) { 2237 throw new IllegalStateException 2238 ("getKeyStore() must be called first"); 2239 } 2240 return protection; 2241 } 2242 }; 2243 } 2244 2245 } 2246 2247 static class SimpleLoadStoreParameter implements LoadStoreParameter { 2248 2249 private final ProtectionParameter protection; 2250 2251 SimpleLoadStoreParameter(ProtectionParameter protection) { 2252 this.protection = protection; 2253 } 2254 2255 public ProtectionParameter getProtectionParameter() { 2256 return protection; 2257 } 2258 } 2259 }