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