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