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