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