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