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