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