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