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