1 /* 2 * Copyright (c) 1997, 2014, 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. <p> 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 * <p> 621 * 622 * @return an unmodifiable {@code Set} of attributes, possibly empty 623 * 624 * @since 1.8 625 */ 626 @Override 627 public Set<Attribute> getAttributes() { 628 return attributes; 629 } 630 631 /** 632 * Returns a string representation of this PrivateKeyEntry. 633 * @return a string representation of this PrivateKeyEntry. 634 */ 635 public String toString() { 636 StringBuilder sb = new StringBuilder(); 637 sb.append("Private key entry and certificate chain with " 638 + chain.length + " elements:\r\n"); 639 for (Certificate cert : chain) { 640 sb.append(cert); 641 sb.append("\r\n"); 642 } 643 return sb.toString(); 644 } 645 646 } 647 648 /** 649 * A {@code KeyStore} entry that holds a {@code SecretKey}. 650 * 651 * @since 1.5 652 */ 653 public static final class SecretKeyEntry implements Entry { 654 655 private final SecretKey sKey; 656 private final Set<Attribute> attributes; 657 658 /** 659 * Constructs a {@code SecretKeyEntry} with a 660 * {@code SecretKey}. 661 * 662 * @param secretKey the {@code SecretKey} 663 * 664 * @exception NullPointerException if {@code secretKey} 665 * is {@code null} 666 */ 667 public SecretKeyEntry(SecretKey secretKey) { 668 if (secretKey == null) { 669 throw new NullPointerException("invalid null input"); 670 } 671 this.sKey = secretKey; 672 this.attributes = Collections.<Attribute>emptySet(); 673 } 674 675 /** 676 * Constructs a {@code SecretKeyEntry} with a {@code SecretKey} and 677 * associated entry attributes. 678 * 679 * <p> The specified {@code attributes} is cloned before it is stored 680 * in the new {@code SecretKeyEntry} object. 681 * 682 * @param secretKey the {@code SecretKey} 683 * @param attributes the attributes 684 * 685 * @exception NullPointerException if {@code secretKey} or 686 * {@code attributes} is {@code null} 687 * 688 * @since 1.8 689 */ 690 public SecretKeyEntry(SecretKey secretKey, Set<Attribute> attributes) { 691 692 if (secretKey == null || attributes == null) { 693 throw new NullPointerException("invalid null input"); 694 } 695 this.sKey = secretKey; 696 this.attributes = 697 Collections.unmodifiableSet(new HashSet<>(attributes)); 698 } 699 700 /** 701 * Gets the {@code SecretKey} from this entry. 702 * 703 * @return the {@code SecretKey} from this entry 704 */ 705 public SecretKey getSecretKey() { 706 return sKey; 707 } 708 709 /** 710 * Retrieves the attributes associated with an entry. 711 * <p> 712 * 713 * @return an unmodifiable {@code Set} of attributes, possibly empty 714 * 715 * @since 1.8 716 */ 717 @Override 718 public Set<Attribute> getAttributes() { 719 return attributes; 720 } 721 722 /** 723 * Returns a string representation of this SecretKeyEntry. 724 * @return a string representation of this SecretKeyEntry. 725 */ 726 public String toString() { 727 return "Secret key entry with algorithm " + sKey.getAlgorithm(); 728 } 729 } 730 731 /** 732 * A {@code KeyStore} entry that holds a trusted 733 * {@code Certificate}. 734 * 735 * @since 1.5 736 */ 737 public static final class TrustedCertificateEntry implements Entry { 738 739 private final Certificate cert; 740 private final Set<Attribute> attributes; 741 742 /** 743 * Constructs a {@code TrustedCertificateEntry} with a 744 * trusted {@code Certificate}. 745 * 746 * @param trustedCert the trusted {@code Certificate} 747 * 748 * @exception NullPointerException if 749 * {@code trustedCert} is {@code null} 750 */ 751 public TrustedCertificateEntry(Certificate trustedCert) { 752 if (trustedCert == null) { 753 throw new NullPointerException("invalid null input"); 754 } 755 this.cert = trustedCert; 756 this.attributes = Collections.<Attribute>emptySet(); 757 } 758 759 /** 760 * Constructs a {@code TrustedCertificateEntry} with a 761 * trusted {@code Certificate} and associated entry attributes. 762 * 763 * <p> The specified {@code attributes} is cloned before it is stored 764 * in the new {@code TrustedCertificateEntry} object. 765 * 766 * @param trustedCert the trusted {@code Certificate} 767 * @param attributes the attributes 768 * 769 * @exception NullPointerException if {@code trustedCert} or 770 * {@code attributes} is {@code null} 771 * 772 * @since 1.8 773 */ 774 public TrustedCertificateEntry(Certificate trustedCert, 775 Set<Attribute> attributes) { 776 if (trustedCert == null || attributes == null) { 777 throw new NullPointerException("invalid null input"); 778 } 779 this.cert = trustedCert; 780 this.attributes = 781 Collections.unmodifiableSet(new HashSet<>(attributes)); 782 } 783 784 /** 785 * Gets the trusted {@code Certficate} from this entry. 786 * 787 * @return the trusted {@code Certificate} from this entry 788 */ 789 public Certificate getTrustedCertificate() { 790 return cert; 791 } 792 793 /** 794 * Retrieves the attributes associated with an entry. 795 * <p> 796 * 797 * @return an unmodifiable {@code Set} of attributes, possibly empty 798 * 799 * @since 1.8 800 */ 801 @Override 802 public Set<Attribute> getAttributes() { 803 return attributes; 804 } 805 806 /** 807 * Returns a string representation of this TrustedCertificateEntry. 808 * @return a string representation of this TrustedCertificateEntry. 809 */ 810 public String toString() { 811 return "Trusted certificate entry:\r\n" + cert.toString(); 812 } 813 } 814 815 /** 816 * Creates a KeyStore object of the given type, and encapsulates the given 817 * provider implementation (SPI object) in it. 818 * 819 * @param keyStoreSpi the provider implementation. 820 * @param provider the provider. 821 * @param type the keystore type. 822 */ 823 protected KeyStore(KeyStoreSpi keyStoreSpi, Provider provider, String type) 824 { 825 this.keyStoreSpi = keyStoreSpi; 826 this.provider = provider; 827 this.type = type; 828 829 if (!skipDebug && pdebug != null) { 830 pdebug.println("KeyStore." + type.toUpperCase() + " type from: " + 831 this.provider.getName()); 832 } 833 } 834 835 /** 836 * Returns a keystore object of the specified type. 837 * 838 * <p> This method traverses the list of registered security Providers, 839 * starting with the most preferred Provider. 840 * A new KeyStore object encapsulating the 841 * KeyStoreSpi implementation from the first 842 * Provider that supports the specified type is returned. 843 * 844 * <p> Note that the list of registered providers may be retrieved via 845 * the {@link Security#getProviders() Security.getProviders()} method. 846 * 847 * @param type the type of keystore. 848 * See the KeyStore section in the <a href= 849 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore"> 850 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 851 * for information about standard keystore types. 852 * 853 * @return a keystore object of the specified type. 854 * 855 * @exception KeyStoreException if no Provider supports a 856 * KeyStoreSpi implementation for the 857 * specified type. 858 * 859 * @see Provider 860 */ 861 public static KeyStore getInstance(String type) 862 throws KeyStoreException 863 { 864 try { 865 Object[] objs = Security.getImpl(type, "KeyStore", (String)null); 866 return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type); 867 } catch (NoSuchAlgorithmException nsae) { 868 throw new KeyStoreException(type + " not found", nsae); 869 } catch (NoSuchProviderException nspe) { 870 throw new KeyStoreException(type + " not found", nspe); 871 } 872 } 873 874 /** 875 * Returns a keystore object of the specified type. 876 * 877 * <p> A new KeyStore object encapsulating the 878 * KeyStoreSpi implementation from the specified provider 879 * is returned. The specified provider must be registered 880 * in the security provider list. 881 * 882 * <p> Note that the list of registered providers may be retrieved via 883 * the {@link Security#getProviders() Security.getProviders()} method. 884 * 885 * @param type the type of keystore. 886 * See the KeyStore section in the <a href= 887 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore"> 888 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 889 * for information about standard keystore types. 890 * 891 * @param provider the name of the provider. 892 * 893 * @return a keystore object of the specified type. 894 * 895 * @exception KeyStoreException if a KeyStoreSpi 896 * implementation for the specified type is not 897 * available from the specified provider. 898 * 899 * @exception NoSuchProviderException if the specified provider is not 900 * registered in the security provider list. 901 * 902 * @exception IllegalArgumentException if the provider name is null 903 * or empty. 904 * 905 * @see Provider 906 */ 907 public static KeyStore getInstance(String type, String provider) 908 throws KeyStoreException, NoSuchProviderException 909 { 910 if (provider == null || provider.length() == 0) 911 throw new IllegalArgumentException("missing provider"); 912 try { 913 Object[] objs = Security.getImpl(type, "KeyStore", provider); 914 return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type); 915 } catch (NoSuchAlgorithmException nsae) { 916 throw new KeyStoreException(type + " not found", nsae); 917 } 918 } 919 920 /** 921 * Returns a keystore object of the specified type. 922 * 923 * <p> A new KeyStore object encapsulating the 924 * KeyStoreSpi implementation from the specified Provider 925 * object is returned. Note that the specified Provider object 926 * does not have to be registered in the provider list. 927 * 928 * @param type the type of keystore. 929 * See the KeyStore section in the <a href= 930 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore"> 931 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 932 * for information about standard keystore types. 933 * 934 * @param provider the provider. 935 * 936 * @return a keystore object of the specified type. 937 * 938 * @exception KeyStoreException if KeyStoreSpi 939 * implementation for the specified type is not available 940 * from the specified Provider object. 941 * 942 * @exception IllegalArgumentException if the specified provider is null. 943 * 944 * @see Provider 945 * 946 * @since 1.4 947 */ 948 public static KeyStore getInstance(String type, Provider provider) 949 throws KeyStoreException 950 { 951 if (provider == null) 952 throw new IllegalArgumentException("missing provider"); 953 try { 954 Object[] objs = Security.getImpl(type, "KeyStore", provider); 955 return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type); 956 } catch (NoSuchAlgorithmException nsae) { 957 throw new KeyStoreException(type + " not found", nsae); 958 } 959 } 960 961 /** 962 * Returns the default keystore type as specified by the 963 * {@code keystore.type} security property, or the string 964 * {@literal "jks"} (acronym for {@literal "Java keystore"}) 965 * if no such property exists. 966 * 967 * <p>The default keystore type can be used by applications that do not 968 * want to use a hard-coded keystore type when calling one of the 969 * {@code getInstance} methods, and want to provide a default keystore 970 * type in case a user does not specify its own. 971 * 972 * <p>The default keystore type can be changed by setting the value of the 973 * {@code keystore.type} security property to the desired keystore type. 974 * 975 * @return the default keystore type as specified by the 976 * {@code keystore.type} security property, or the string {@literal "jks"} 977 * if no such property exists. 978 * @see java.security.Security security properties 979 */ 980 public final static String getDefaultType() { 981 String kstype; 982 kstype = AccessController.doPrivileged(new PrivilegedAction<String>() { 983 public String run() { 984 return Security.getProperty(KEYSTORE_TYPE); 985 } 986 }); 987 if (kstype == null) { 988 kstype = "jks"; 989 } 990 return kstype; 991 } 992 993 /** 994 * Returns the provider of this keystore. 995 * 996 * @return the provider of this keystore. 997 */ 998 public final Provider getProvider() 999 { 1000 return this.provider; 1001 } 1002 1003 /** 1004 * Returns the type of this keystore. 1005 * 1006 * @return the type of this keystore. 1007 */ 1008 public final String getType() 1009 { 1010 return this.type; 1011 } 1012 1013 /** 1014 * Returns the key associated with the given alias, using the given 1015 * password to recover it. The key must have been associated with 1016 * the alias by a call to {@code setKeyEntry}, 1017 * or by a call to {@code setEntry} with a 1018 * {@code PrivateKeyEntry} or {@code SecretKeyEntry}. 1019 * 1020 * @param alias the alias name 1021 * @param password the password for recovering the key 1022 * 1023 * @return the requested key, or null if the given alias does not exist 1024 * or does not identify a key-related entry. 1025 * 1026 * @exception KeyStoreException if the keystore has not been initialized 1027 * (loaded). 1028 * @exception NoSuchAlgorithmException if the algorithm for recovering the 1029 * key cannot be found 1030 * @exception UnrecoverableKeyException if the key cannot be recovered 1031 * (e.g., the given password is wrong). 1032 */ 1033 public final Key getKey(String alias, char[] password) 1034 throws KeyStoreException, NoSuchAlgorithmException, 1035 UnrecoverableKeyException 1036 { 1037 if (!initialized) { 1038 throw new KeyStoreException("Uninitialized keystore"); 1039 } 1040 return keyStoreSpi.engineGetKey(alias, password); 1041 } 1042 1043 /** 1044 * Returns the certificate chain associated with the given alias. 1045 * The certificate chain must have been associated with the alias 1046 * by a call to {@code setKeyEntry}, 1047 * or by a call to {@code setEntry} with a 1048 * {@code PrivateKeyEntry}. 1049 * 1050 * @param alias the alias name 1051 * 1052 * @return the certificate chain (ordered with the user's certificate first 1053 * followed by zero or more certificate authorities), or null if the given alias 1054 * does not exist or does not contain a certificate chain 1055 * 1056 * @exception KeyStoreException if the keystore has not been initialized 1057 * (loaded). 1058 */ 1059 public final Certificate[] getCertificateChain(String alias) 1060 throws KeyStoreException 1061 { 1062 if (!initialized) { 1063 throw new KeyStoreException("Uninitialized keystore"); 1064 } 1065 return keyStoreSpi.engineGetCertificateChain(alias); 1066 } 1067 1068 /** 1069 * Returns the certificate associated with the given alias. 1070 * 1071 * <p> If the given alias name identifies an entry 1072 * created by a call to {@code setCertificateEntry}, 1073 * or created by a call to {@code setEntry} with a 1074 * {@code TrustedCertificateEntry}, 1075 * then the trusted certificate contained in that entry is returned. 1076 * 1077 * <p> If the given alias name identifies an entry 1078 * created by a call to {@code setKeyEntry}, 1079 * or created by a call to {@code setEntry} with a 1080 * {@code PrivateKeyEntry}, 1081 * then the first element of the certificate chain in that entry 1082 * is returned. 1083 * 1084 * @param alias the alias name 1085 * 1086 * @return the certificate, or null if the given alias does not exist or 1087 * does not contain a certificate. 1088 * 1089 * @exception KeyStoreException if the keystore has not been initialized 1090 * (loaded). 1091 */ 1092 public final Certificate getCertificate(String alias) 1093 throws KeyStoreException 1094 { 1095 if (!initialized) { 1096 throw new KeyStoreException("Uninitialized keystore"); 1097 } 1098 return keyStoreSpi.engineGetCertificate(alias); 1099 } 1100 1101 /** 1102 * Returns the creation date of the entry identified by the given alias. 1103 * 1104 * @param alias the alias name 1105 * 1106 * @return the creation date of this entry, or null if the given alias does 1107 * not exist 1108 * 1109 * @exception KeyStoreException if the keystore has not been initialized 1110 * (loaded). 1111 */ 1112 public final Date getCreationDate(String alias) 1113 throws KeyStoreException 1114 { 1115 if (!initialized) { 1116 throw new KeyStoreException("Uninitialized keystore"); 1117 } 1118 return keyStoreSpi.engineGetCreationDate(alias); 1119 } 1120 1121 /** 1122 * Assigns the given key to the given alias, protecting it with the given 1123 * password. 1124 * 1125 * <p>If the given key is of type {@code java.security.PrivateKey}, 1126 * it must be accompanied by a certificate chain certifying the 1127 * corresponding public key. 1128 * 1129 * <p>If the given alias already exists, the keystore information 1130 * associated with it is overridden by the given key (and possibly 1131 * certificate chain). 1132 * 1133 * @param alias the alias name 1134 * @param key the key to be associated with the alias 1135 * @param password the password to protect the key 1136 * @param chain the certificate chain for the corresponding public 1137 * key (only required if the given key is of type 1138 * {@code java.security.PrivateKey}). 1139 * 1140 * @exception KeyStoreException if the keystore has not been initialized 1141 * (loaded), the given key cannot be protected, or this operation fails 1142 * for some other reason 1143 */ 1144 public final void setKeyEntry(String alias, Key key, char[] password, 1145 Certificate[] chain) 1146 throws KeyStoreException 1147 { 1148 if (!initialized) { 1149 throw new KeyStoreException("Uninitialized keystore"); 1150 } 1151 if ((key instanceof PrivateKey) && 1152 (chain == null || chain.length == 0)) { 1153 throw new IllegalArgumentException("Private key must be " 1154 + "accompanied by certificate " 1155 + "chain"); 1156 } 1157 keyStoreSpi.engineSetKeyEntry(alias, key, password, chain); 1158 } 1159 1160 /** 1161 * Assigns the given key (that has already been protected) to the given 1162 * alias. 1163 * 1164 * <p>If the protected key is of type 1165 * {@code java.security.PrivateKey}, it must be accompanied by a 1166 * certificate chain certifying the corresponding public key. If the 1167 * underlying keystore implementation is of type {@code jks}, 1168 * {@code key} must be encoded as an 1169 * {@code EncryptedPrivateKeyInfo} as defined in the PKCS #8 standard. 1170 * 1171 * <p>If the given alias already exists, the keystore information 1172 * associated with it is overridden by the given key (and possibly 1173 * certificate chain). 1174 * 1175 * @param alias the alias name 1176 * @param key the key (in protected format) to be associated with the alias 1177 * @param chain the certificate chain for the corresponding public 1178 * key (only useful if the protected key is of type 1179 * {@code java.security.PrivateKey}). 1180 * 1181 * @exception KeyStoreException if the keystore has not been initialized 1182 * (loaded), or if this operation fails for some other reason. 1183 */ 1184 public final void setKeyEntry(String alias, byte[] key, 1185 Certificate[] chain) 1186 throws KeyStoreException 1187 { 1188 if (!initialized) { 1189 throw new KeyStoreException("Uninitialized keystore"); 1190 } 1191 keyStoreSpi.engineSetKeyEntry(alias, key, chain); 1192 } 1193 1194 /** 1195 * Assigns the given trusted certificate to the given alias. 1196 * 1197 * <p> If the given alias identifies an existing entry 1198 * created by a call to {@code setCertificateEntry}, 1199 * or created by a call to {@code setEntry} with a 1200 * {@code TrustedCertificateEntry}, 1201 * the trusted certificate in the existing entry 1202 * is overridden by the given certificate. 1203 * 1204 * @param alias the alias name 1205 * @param cert the certificate 1206 * 1207 * @exception KeyStoreException if the keystore has not been initialized, 1208 * or the given alias already exists and does not identify an 1209 * entry containing a trusted certificate, 1210 * or this operation fails for some other reason. 1211 */ 1212 public final void setCertificateEntry(String alias, Certificate cert) 1213 throws KeyStoreException 1214 { 1215 if (!initialized) { 1216 throw new KeyStoreException("Uninitialized keystore"); 1217 } 1218 keyStoreSpi.engineSetCertificateEntry(alias, cert); 1219 } 1220 1221 /** 1222 * Deletes the entry identified by the given alias from this keystore. 1223 * 1224 * @param alias the alias name 1225 * 1226 * @exception KeyStoreException if the keystore has not been initialized, 1227 * or if the entry cannot be removed. 1228 */ 1229 public final void deleteEntry(String alias) 1230 throws KeyStoreException 1231 { 1232 if (!initialized) { 1233 throw new KeyStoreException("Uninitialized keystore"); 1234 } 1235 keyStoreSpi.engineDeleteEntry(alias); 1236 } 1237 1238 /** 1239 * Lists all the alias names of this keystore. 1240 * 1241 * @return enumeration of the alias names 1242 * 1243 * @exception KeyStoreException if the keystore has not been initialized 1244 * (loaded). 1245 */ 1246 public final Enumeration<String> aliases() 1247 throws KeyStoreException 1248 { 1249 if (!initialized) { 1250 throw new KeyStoreException("Uninitialized keystore"); 1251 } 1252 return keyStoreSpi.engineAliases(); 1253 } 1254 1255 /** 1256 * Checks if the given alias exists in this keystore. 1257 * 1258 * @param alias the alias name 1259 * 1260 * @return true if the alias exists, false otherwise 1261 * 1262 * @exception KeyStoreException if the keystore has not been initialized 1263 * (loaded). 1264 */ 1265 public final boolean containsAlias(String alias) 1266 throws KeyStoreException 1267 { 1268 if (!initialized) { 1269 throw new KeyStoreException("Uninitialized keystore"); 1270 } 1271 return keyStoreSpi.engineContainsAlias(alias); 1272 } 1273 1274 /** 1275 * Retrieves the number of entries in this keystore. 1276 * 1277 * @return the number of entries in this keystore 1278 * 1279 * @exception KeyStoreException if the keystore has not been initialized 1280 * (loaded). 1281 */ 1282 public final int size() 1283 throws KeyStoreException 1284 { 1285 if (!initialized) { 1286 throw new KeyStoreException("Uninitialized keystore"); 1287 } 1288 return keyStoreSpi.engineSize(); 1289 } 1290 1291 /** 1292 * Returns true if the entry identified by the given alias 1293 * was created by a call to {@code setKeyEntry}, 1294 * or created by a call to {@code setEntry} with a 1295 * {@code PrivateKeyEntry} or a {@code SecretKeyEntry}. 1296 * 1297 * @param alias the alias for the keystore entry to be checked 1298 * 1299 * @return true if the entry identified by the given alias is a 1300 * key-related entry, false otherwise. 1301 * 1302 * @exception KeyStoreException if the keystore has not been initialized 1303 * (loaded). 1304 */ 1305 public final boolean isKeyEntry(String alias) 1306 throws KeyStoreException 1307 { 1308 if (!initialized) { 1309 throw new KeyStoreException("Uninitialized keystore"); 1310 } 1311 return keyStoreSpi.engineIsKeyEntry(alias); 1312 } 1313 1314 /** 1315 * Returns true if the entry identified by the given alias 1316 * was created by a call to {@code setCertificateEntry}, 1317 * or created by a call to {@code setEntry} with a 1318 * {@code TrustedCertificateEntry}. 1319 * 1320 * @param alias the alias for the keystore entry to be checked 1321 * 1322 * @return true if the entry identified by the given alias contains a 1323 * trusted certificate, false otherwise. 1324 * 1325 * @exception KeyStoreException if the keystore has not been initialized 1326 * (loaded). 1327 */ 1328 public final boolean isCertificateEntry(String alias) 1329 throws KeyStoreException 1330 { 1331 if (!initialized) { 1332 throw new KeyStoreException("Uninitialized keystore"); 1333 } 1334 return keyStoreSpi.engineIsCertificateEntry(alias); 1335 } 1336 1337 /** 1338 * Returns the (alias) name of the first keystore entry whose certificate 1339 * matches the given certificate. 1340 * 1341 * <p> This method attempts to match the given certificate with each 1342 * keystore entry. If the entry being considered was 1343 * created by a call to {@code setCertificateEntry}, 1344 * or created by a call to {@code setEntry} with a 1345 * {@code TrustedCertificateEntry}, 1346 * then the given certificate is compared to that entry's certificate. 1347 * 1348 * <p> If the entry being considered was 1349 * created by a call to {@code setKeyEntry}, 1350 * or created by a call to {@code setEntry} with a 1351 * {@code PrivateKeyEntry}, 1352 * then the given certificate is compared to the first 1353 * element of that entry's certificate chain. 1354 * 1355 * @param cert the certificate to match with. 1356 * 1357 * @return the alias name of the first entry with a matching certificate, 1358 * or null if no such entry exists in this keystore. 1359 * 1360 * @exception KeyStoreException if the keystore has not been initialized 1361 * (loaded). 1362 */ 1363 public final String getCertificateAlias(Certificate cert) 1364 throws KeyStoreException 1365 { 1366 if (!initialized) { 1367 throw new KeyStoreException("Uninitialized keystore"); 1368 } 1369 return keyStoreSpi.engineGetCertificateAlias(cert); 1370 } 1371 1372 /** 1373 * Stores this keystore to the given output stream, and protects its 1374 * integrity with the given password. 1375 * 1376 * @param stream the output stream to which this keystore is written. 1377 * @param password the password to generate the keystore integrity check 1378 * 1379 * @exception KeyStoreException if the keystore has not been initialized 1380 * (loaded). 1381 * @exception IOException if there was an I/O problem with data 1382 * @exception NoSuchAlgorithmException if the appropriate data integrity 1383 * algorithm could not be found 1384 * @exception CertificateException if any of the certificates included in 1385 * the keystore data could not be stored 1386 */ 1387 public final void store(OutputStream stream, char[] password) 1388 throws KeyStoreException, IOException, NoSuchAlgorithmException, 1389 CertificateException 1390 { 1391 if (!initialized) { 1392 throw new KeyStoreException("Uninitialized keystore"); 1393 } 1394 keyStoreSpi.engineStore(stream, password); 1395 } 1396 1397 /** 1398 * Stores this keystore using the given {@code LoadStoreParameter}. 1399 * 1400 * @param param the {@code LoadStoreParameter} 1401 * that specifies how to store the keystore, 1402 * which may be {@code null} 1403 * 1404 * @exception IllegalArgumentException if the given 1405 * {@code LoadStoreParameter} 1406 * input is not recognized 1407 * @exception KeyStoreException if the keystore has not been initialized 1408 * (loaded) 1409 * @exception IOException if there was an I/O problem with data 1410 * @exception NoSuchAlgorithmException if the appropriate data integrity 1411 * algorithm could not be found 1412 * @exception CertificateException if any of the certificates included in 1413 * the keystore data could not be stored 1414 * 1415 * @since 1.5 1416 */ 1417 public final void store(LoadStoreParameter param) 1418 throws KeyStoreException, IOException, 1419 NoSuchAlgorithmException, CertificateException { 1420 if (!initialized) { 1421 throw new KeyStoreException("Uninitialized keystore"); 1422 } 1423 keyStoreSpi.engineStore(param); 1424 } 1425 1426 /** 1427 * Loads this KeyStore from the given input stream. 1428 * 1429 * <p>A password may be given to unlock the keystore 1430 * (e.g. the keystore resides on a hardware token device), 1431 * or to check the integrity of the keystore data. 1432 * If a password is not given for integrity checking, 1433 * then integrity checking is not performed. 1434 * 1435 * <p>In order to create an empty keystore, or if the keystore cannot 1436 * be initialized from a stream, pass {@code null} 1437 * as the {@code stream} argument. 1438 * 1439 * <p> Note that if this keystore has already been loaded, it is 1440 * reinitialized and loaded again from the given input stream. 1441 * 1442 * @param stream the input stream from which the keystore is loaded, 1443 * or {@code null} 1444 * @param password the password used to check the integrity of 1445 * the keystore, the password used to unlock the keystore, 1446 * or {@code null} 1447 * 1448 * @exception IOException if there is an I/O or format problem with the 1449 * keystore data, if a password is required but not given, 1450 * or if the given password was incorrect. If the error is due to a 1451 * wrong password, the {@link Throwable#getCause cause} of the 1452 * {@code IOException} should be an 1453 * {@code UnrecoverableKeyException} 1454 * @exception NoSuchAlgorithmException if the algorithm used to check 1455 * the integrity of the keystore cannot be found 1456 * @exception CertificateException if any of the certificates in the 1457 * keystore could not be loaded 1458 */ 1459 public final void load(InputStream stream, char[] password) 1460 throws IOException, NoSuchAlgorithmException, CertificateException 1461 { 1462 keyStoreSpi.engineLoad(stream, password); 1463 initialized = true; 1464 } 1465 1466 /** 1467 * Loads this keystore using the given {@code LoadStoreParameter}. 1468 * 1469 * <p> Note that if this KeyStore has already been loaded, it is 1470 * reinitialized and loaded again from the given parameter. 1471 * 1472 * @param param the {@code LoadStoreParameter} 1473 * that specifies how to load the keystore, 1474 * which may be {@code null} 1475 * 1476 * @exception IllegalArgumentException if the given 1477 * {@code LoadStoreParameter} 1478 * input is not recognized 1479 * @exception IOException if there is an I/O or format problem with the 1480 * keystore data. If the error is due to an incorrect 1481 * {@code ProtectionParameter} (e.g. wrong password) 1482 * the {@link Throwable#getCause cause} of the 1483 * {@code IOException} should be an 1484 * {@code UnrecoverableKeyException} 1485 * @exception NoSuchAlgorithmException if the algorithm used to check 1486 * the integrity of the keystore cannot be found 1487 * @exception CertificateException if any of the certificates in the 1488 * keystore could not be loaded 1489 * 1490 * @since 1.5 1491 */ 1492 public final void load(LoadStoreParameter param) 1493 throws IOException, NoSuchAlgorithmException, 1494 CertificateException { 1495 1496 keyStoreSpi.engineLoad(param); 1497 initialized = true; 1498 } 1499 1500 /** 1501 * Gets a keystore {@code Entry} for the specified alias 1502 * with the specified protection parameter. 1503 * 1504 * @param alias get the keystore {@code Entry} for this alias 1505 * @param protParam the {@code ProtectionParameter} 1506 * used to protect the {@code Entry}, 1507 * which may be {@code null} 1508 * 1509 * @return the keystore {@code Entry} for the specified alias, 1510 * or {@code null} if there is no such entry 1511 * 1512 * @exception NullPointerException if 1513 * {@code alias} is {@code null} 1514 * @exception NoSuchAlgorithmException if the algorithm for recovering the 1515 * entry cannot be found 1516 * @exception UnrecoverableEntryException if the specified 1517 * {@code protParam} were insufficient or invalid 1518 * @exception UnrecoverableKeyException if the entry is a 1519 * {@code PrivateKeyEntry} or {@code SecretKeyEntry} 1520 * and the specified {@code protParam} does not contain 1521 * the information needed to recover the key (e.g. wrong password) 1522 * @exception KeyStoreException if the keystore has not been initialized 1523 * (loaded). 1524 * @see #setEntry(String, KeyStore.Entry, KeyStore.ProtectionParameter) 1525 * 1526 * @since 1.5 1527 */ 1528 public final Entry getEntry(String alias, ProtectionParameter protParam) 1529 throws NoSuchAlgorithmException, UnrecoverableEntryException, 1530 KeyStoreException { 1531 1532 if (alias == null) { 1533 throw new NullPointerException("invalid null input"); 1534 } 1535 if (!initialized) { 1536 throw new KeyStoreException("Uninitialized keystore"); 1537 } 1538 return keyStoreSpi.engineGetEntry(alias, protParam); 1539 } 1540 1541 /** 1542 * Saves a keystore {@code Entry} under the specified alias. 1543 * The protection parameter is used to protect the 1544 * {@code Entry}. 1545 * 1546 * <p> If an entry already exists for the specified alias, 1547 * it is overridden. 1548 * 1549 * @param alias save the keystore {@code Entry} under this alias 1550 * @param entry the {@code Entry} to save 1551 * @param protParam the {@code ProtectionParameter} 1552 * used to protect the {@code Entry}, 1553 * which may be {@code null} 1554 * 1555 * @exception NullPointerException if 1556 * {@code alias} or {@code entry} 1557 * is {@code null} 1558 * @exception KeyStoreException if the keystore has not been initialized 1559 * (loaded), or if this operation fails for some other reason 1560 * 1561 * @see #getEntry(String, KeyStore.ProtectionParameter) 1562 * 1563 * @since 1.5 1564 */ 1565 public final void setEntry(String alias, Entry entry, 1566 ProtectionParameter protParam) 1567 throws KeyStoreException { 1568 if (alias == null || entry == null) { 1569 throw new NullPointerException("invalid null input"); 1570 } 1571 if (!initialized) { 1572 throw new KeyStoreException("Uninitialized keystore"); 1573 } 1574 keyStoreSpi.engineSetEntry(alias, entry, protParam); 1575 } 1576 1577 /** 1578 * Determines if the keystore {@code Entry} for the specified 1579 * {@code alias} is an instance or subclass of the specified 1580 * {@code entryClass}. 1581 * 1582 * @param alias the alias name 1583 * @param entryClass the entry class 1584 * 1585 * @return true if the keystore {@code Entry} for the specified 1586 * {@code alias} is an instance or subclass of the 1587 * specified {@code entryClass}, false otherwise 1588 * 1589 * @exception NullPointerException if 1590 * {@code alias} or {@code entryClass} 1591 * is {@code null} 1592 * @exception KeyStoreException if the keystore has not been 1593 * initialized (loaded) 1594 * 1595 * @since 1.5 1596 */ 1597 public final boolean 1598 entryInstanceOf(String alias, 1599 Class<? extends KeyStore.Entry> entryClass) 1600 throws KeyStoreException 1601 { 1602 1603 if (alias == null || entryClass == null) { 1604 throw new NullPointerException("invalid null input"); 1605 } 1606 if (!initialized) { 1607 throw new KeyStoreException("Uninitialized keystore"); 1608 } 1609 return keyStoreSpi.engineEntryInstanceOf(alias, entryClass); 1610 } 1611 1612 /** 1613 * Returns a loaded keystore object of the appropriate keystore type. 1614 * First the keystore type is determined by probing the specified file. 1615 * Then a keystore object is instantiated and loaded using the data from 1616 * that file. 1617 * A password may be supplied to unlock the keystore data or perform an 1618 * integrity check. 1619 * 1620 * <p> 1621 * This method traverses the list of registered security {@link Providers}, 1622 * starting with the most preferred Provider. 1623 * For each {@link KeyStoreSpi} implementation supported by a Provider, 1624 * it invokes the {@link engineProbe} method to determine if it supports 1625 * the specified keystore. 1626 * A new KeyStore object is returned that encapsulates the KeyStoreSpi 1627 * implementation from the first Provider that supports the specified file. 1628 * 1629 * <p> Note that the list of registered providers may be retrieved via 1630 * the {@link Security#getProviders() Security.getProviders()} method. 1631 * 1632 * @param file the keystore file 1633 * @param password the keystore password, which may be {@code null} 1634 * 1635 * @return a keystore object loaded with keystore data 1636 * 1637 * @throws KeyStoreException if no Provider supports a KeyStoreSpi 1638 * implementation for the specified keystore file. 1639 * @throws IOException if there is an I/O or format problem with the 1640 * keystore data, if a password is required but not given, 1641 * or if the given password was incorrect. If the error is 1642 * due to a wrong password, the {@link Throwable#getCause cause} 1643 * of the {@code IOException} should be an 1644 * {@code UnrecoverableKeyException}. 1645 * @throws NoSuchAlgorithmException if the algorithm used to check the 1646 * integrity of the keystore cannot be found. 1647 * @throws CertificateException if any of the certificates in the 1648 * keystore could not be loaded. 1649 * @throws IllegalArgumentException if file does not exist or does not 1650 * refer to a normal file. 1651 * @throws NullPointerException if file is {@code null}. 1652 * @throws SecurityException if a security manager exists and its 1653 * {@link java.lang.SecurityManager#checkRead} method denies 1654 * read access to the specified file. 1655 * 1656 * @see Provider 1657 * 1658 * @since 1.9 1659 */ 1660 public static final KeyStore getInstance(File file, char[] password) 1661 throws KeyStoreException, IOException, NoSuchAlgorithmException, 1662 CertificateException { 1663 return getInstance(file, password, null, true); 1664 } 1665 1666 /** 1667 * Returns a loaded keystore object of the appropriate keystore type. 1668 * First the keystore type is determined by probing the specified file. 1669 * Then a keystore object is instantiated and loaded using the data from 1670 * that file. 1671 * A {@code LoadStoreParameter} may be supplied which specifies how to 1672 * unlock the keystore data or perform an integrity check. 1673 * 1674 * <p> 1675 * This method traverses the list of registered security {@link Providers}, 1676 * starting with the most preferred Provider. 1677 * For each {@link KeyStoreSpi} implementation supported by a Provider, 1678 * it invokes the {@link engineProbe} method to determine if it supports 1679 * 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 }