1. /*
  2. * @(#)KeyStore.java 1.32 03/01/23
  3. *
  4. * Copyright 2003 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.CertificateException;
  11. import java.util.*;
  12. /**
  13. * This class represents an in-memory collection of keys and certificates.
  14. * It manages two types of entries:
  15. *
  16. * <ul>
  17. * <li><b>Key Entry</b>
  18. * <p>This type of keystore entry holds very sensitive cryptographic key
  19. * information, which is stored in a protected format to prevent unauthorized
  20. * access.
  21. *
  22. * <p>Typically, a key stored in this type of entry is a secret key, or a
  23. * private key accompanied by the certificate chain for the corresponding
  24. * public key.
  25. *
  26. * <p>Private keys and certificate chains are used by a given entity for
  27. * self-authentication. Applications for this authentication include software
  28. * distribution organizations which sign JAR files as part of releasing
  29. * and/or licensing software.<p>
  30. *
  31. * <li><b>Trusted Certificate Entry</b>
  32. * <p>This type of entry contains a single public key certificate belonging to
  33. * another party. It is called a <i>trusted certificate</i> because the
  34. * keystore owner trusts that the public key in the certificate indeed belongs
  35. * to the identity identified by the <i>subject</i> (owner) of the
  36. * 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 public key algorithms.
  46. *
  47. * <p>Whether keystores are persistent, and the mechanisms used by the
  48. * keystore if it is persistent, are not specified here. This allows
  49. * use of a variety of techniques for protecting sensitive (e.g., private or
  50. * secret) keys. Smart cards or other integrated cryptographic engines
  51. * (SafeKeyper) are one option, and simpler mechanisms such as files may also
  52. * be used (in a variety of formats).
  53. *
  54. * <p>There are two ways to request a KeyStore object: by
  55. * specifying either just a keystore type, or both a keystore type
  56. * and a package provider.
  57. *
  58. * <ul>
  59. * <li>If just a keystore type is specified:
  60. * <pre>
  61. * KeyStore ks = KeyStore.getInstance("JKS");
  62. * </pre>
  63. * the system will determine if there is an implementation of the keystore type
  64. * requested available in the environment, and if there is more than one, if
  65. * there is a preferred one.<p>
  66. *
  67. * <li>If both a keystore type and a package provider are specified:
  68. * <pre>
  69. * KeyStore ks = KeyStore.getInstance("JKS", "SUN");
  70. * </pre>
  71. * the system will determine if there is an implementation of the
  72. * keystore type in the package requested, and throw an exception if there
  73. * is not.
  74. *
  75. * </ul>
  76. *
  77. * <p>Before a keystore can be accessed, it must be
  78. * {@link #load(java.io.InputStream, char[]) loaded}. In order to create
  79. * an empty keystore, you pass <code>null</code>
  80. * as the <code>InputStream</code> argument to the <code>load</code> method.
  81. *
  82. * @author Jan Luehe
  83. *
  84. * @version 1.32, 01/23/03
  85. *
  86. * @see java.security.PrivateKey
  87. * @see java.security.cert.Certificate
  88. *
  89. * @since 1.2
  90. */
  91. public class KeyStore {
  92. /*
  93. * Constant to lookup in the Security properties file to determine
  94. * the default keystore type.
  95. * In the Security properties file, the default keystore type is given as:
  96. * <pre>
  97. * keystore.type=jks
  98. * </pre>
  99. */
  100. private static final String KEYSTORE_TYPE = "keystore.type";
  101. // The keystore type
  102. private String type;
  103. // The provider
  104. private Provider provider;
  105. // The provider implementation
  106. private KeyStoreSpi keyStoreSpi;
  107. // Has this keystore been initialized (loaded)?
  108. private boolean initialized = false;
  109. /**
  110. * Creates a KeyStore object of the given type, and encapsulates the given
  111. * provider implementation (SPI object) in it.
  112. *
  113. * @param keyStoreSpi the provider implementation.
  114. * @param provider the provider.
  115. * @param type the keystore type.
  116. */
  117. protected KeyStore(KeyStoreSpi keyStoreSpi, Provider provider, String type)
  118. {
  119. this.keyStoreSpi = keyStoreSpi;
  120. this.provider = provider;
  121. this.type = type;
  122. }
  123. /**
  124. * Generates a keystore object of the given type.
  125. *
  126. * <p>If the default provider package provides a keystore implementation
  127. * of the given type, an instance of <code>KeyStore</code> containing that
  128. * implementation is returned. If the requested keystore type is not
  129. * available in the default package, other packages are searched.
  130. *
  131. * @param type the type of keystore.
  132. * See Appendix A in the <a href=
  133. * "../../../guide/security/CryptoSpec.html#AppA">
  134. * Java Cryptography Architecture API Specification & Reference </a>
  135. * for information about standard keystore types.
  136. *
  137. * @return a keystore object of the specified type.
  138. *
  139. * @exception KeyStoreException if the requested keystore type is
  140. * not available in the default provider package or any of the other
  141. * provider packages that were searched.
  142. */
  143. public static KeyStore getInstance(String type)
  144. throws KeyStoreException
  145. {
  146. try {
  147. Object[] objs = Security.getImpl(type, "KeyStore", (String)null);
  148. return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);
  149. } catch(NoSuchAlgorithmException nsae) {
  150. throw new KeyStoreException(type + " not found");
  151. } catch(NoSuchProviderException nspe) {
  152. throw new KeyStoreException(type + " not found");
  153. }
  154. }
  155. /**
  156. * Generates a keystore object for the specified keystore
  157. * type from the specified provider.
  158. *
  159. * @param type the type of keystore.
  160. * See Appendix A in the <a href=
  161. * "../../../guide/security/CryptoSpec.html#AppA">
  162. * Java Cryptography Architecture API Specification & Reference </a>
  163. * for information about standard keystore types.
  164. *
  165. * @param provider the name of the provider.
  166. *
  167. * @return a keystore object of the specified type, as
  168. * supplied by the specified provider.
  169. *
  170. * @exception KeyStoreException if the requested keystore type is not
  171. * available from the provider.
  172. *
  173. * @exception NoSuchProviderException if the provider has not been
  174. * configured.
  175. *
  176. * @exception IllegalArgumentException if the provider name is null
  177. * or empty.
  178. *
  179. * @see Provider
  180. */
  181. public static KeyStore getInstance(String type, String provider)
  182. throws KeyStoreException, NoSuchProviderException
  183. {
  184. if (provider == null || provider.length() == 0)
  185. throw new IllegalArgumentException("missing provider");
  186. try {
  187. Object[] objs = Security.getImpl(type, "KeyStore", provider);
  188. return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);
  189. } catch(NoSuchAlgorithmException nsae) {
  190. throw new KeyStoreException(type + " not found");
  191. }
  192. }
  193. /**
  194. * Generates a keystore object for the specified keystore
  195. * type from the specified provider. Note: the <code>provider</code>
  196. * doesn't have to be registered.
  197. *
  198. * @param type the type of keystore.
  199. * See Appendix A in the <a href=
  200. * "../../../guide/security/CryptoSpec.html#AppA">
  201. * Java Cryptography Architecture API Specification & Reference </a>
  202. * for information about standard keystore types.
  203. *
  204. * @param provider the provider.
  205. *
  206. * @return a keystore object of the specified type, as
  207. * supplied by the specified provider.
  208. *
  209. * @exception KeyStoreException if the requested keystore type is not
  210. * available from the provider.
  211. *
  212. * @exception IllegalArgumentException if the <code>provider</code> is
  213. * null.
  214. *
  215. * @see Provider
  216. *
  217. * @since 1.4
  218. */
  219. public static KeyStore getInstance(String type, Provider provider)
  220. throws KeyStoreException
  221. {
  222. if (provider == null)
  223. throw new IllegalArgumentException("missing provider");
  224. try {
  225. Object[] objs = Security.getImpl(type, "KeyStore", provider);
  226. return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);
  227. } catch(NoSuchAlgorithmException nsae) {
  228. throw new KeyStoreException(type + " not found");
  229. }
  230. }
  231. /**
  232. * Returns the provider of this keystore.
  233. *
  234. * @return the provider of this keystore.
  235. */
  236. public final Provider getProvider()
  237. {
  238. return this.provider;
  239. }
  240. /**
  241. * Returns the type of this keystore.
  242. *
  243. * @return the type of this keystore.
  244. */
  245. public final String getType()
  246. {
  247. return this.type;
  248. }
  249. /**
  250. * Returns the key associated with the given alias, using the given
  251. * password to recover it.
  252. *
  253. * @param alias the alias name
  254. * @param password the password for recovering the key
  255. *
  256. * @return the requested key, or null if the given alias does not exist
  257. * or does not identify a <i>key entry</i>.
  258. *
  259. * @exception KeyStoreException if the keystore has not been initialized
  260. * (loaded).
  261. * @exception NoSuchAlgorithmException if the algorithm for recovering the
  262. * key cannot be found
  263. * @exception UnrecoverableKeyException if the key cannot be recovered
  264. * (e.g., the given password is wrong).
  265. */
  266. public final Key getKey(String alias, char[] password)
  267. throws KeyStoreException, NoSuchAlgorithmException,
  268. UnrecoverableKeyException
  269. {
  270. if (!initialized) {
  271. throw new KeyStoreException("Uninitialized keystore");
  272. }
  273. return keyStoreSpi.engineGetKey(alias, password);
  274. }
  275. /**
  276. * Returns the certificate chain associated with the given alias.
  277. *
  278. * @param alias the alias name
  279. *
  280. * @return the certificate chain (ordered with the user's certificate first
  281. * and the root certificate authority last), or null if the given alias
  282. * does not exist or does not contain a certificate chain (i.e., the given
  283. * alias identifies either a <i>trusted certificate entry</i> or a
  284. * <i>key entry</i> without a certificate chain).
  285. *
  286. * @exception KeyStoreException if the keystore has not been initialized
  287. * (loaded).
  288. */
  289. public final Certificate[] getCertificateChain(String alias)
  290. throws KeyStoreException
  291. {
  292. if (!initialized) {
  293. throw new KeyStoreException("Uninitialized keystore");
  294. }
  295. return keyStoreSpi.engineGetCertificateChain(alias);
  296. }
  297. /**
  298. * Returns the certificate associated with the given alias.
  299. *
  300. * <p>If the given alias name identifies a
  301. * <i>trusted certificate entry</i>, the certificate associated with that
  302. * entry is returned. If the given alias name identifies a
  303. * <i>key entry</i>, the first element of the certificate chain of that
  304. * entry is returned, or null if that entry does not have a certificate
  305. * chain.
  306. *
  307. * @param alias the alias name
  308. *
  309. * @return the certificate, or null if the given alias does not exist or
  310. * does not contain a certificate.
  311. *
  312. * @exception KeyStoreException if the keystore has not been initialized
  313. * (loaded).
  314. */
  315. public final Certificate getCertificate(String alias)
  316. throws KeyStoreException
  317. {
  318. if (!initialized) {
  319. throw new KeyStoreException("Uninitialized keystore");
  320. }
  321. return keyStoreSpi.engineGetCertificate(alias);
  322. }
  323. /**
  324. * Returns the creation date of the entry identified by the given alias.
  325. *
  326. * @param alias the alias name
  327. *
  328. * @return the creation date of this entry, or null if the given alias does
  329. * not exist
  330. *
  331. * @exception KeyStoreException if the keystore has not been initialized
  332. * (loaded).
  333. */
  334. public final Date getCreationDate(String alias)
  335. throws KeyStoreException
  336. {
  337. if (!initialized) {
  338. throw new KeyStoreException("Uninitialized keystore");
  339. }
  340. return keyStoreSpi.engineGetCreationDate(alias);
  341. }
  342. /**
  343. * Assigns the given key to the given alias, protecting it with the given
  344. * password.
  345. *
  346. * <p>If the given key is of type <code>java.security.PrivateKey</code>,
  347. * it must be accompanied by a certificate chain certifying the
  348. * corresponding public key.
  349. *
  350. * <p>If the given alias already exists, the keystore information
  351. * associated with it is overridden by the given key (and possibly
  352. * certificate chain).
  353. *
  354. * @param alias the alias name
  355. * @param key the key to be associated with the alias
  356. * @param password the password to protect the key
  357. * @param chain the certificate chain for the corresponding public
  358. * key (only required if the given key is of type
  359. * <code>java.security.PrivateKey</code>).
  360. *
  361. * @exception KeyStoreException if the keystore has not been initialized
  362. * (loaded), the given key cannot be protected, or this operation fails
  363. * for some other reason
  364. */
  365. public final void setKeyEntry(String alias, Key key, char[] password,
  366. Certificate[] chain)
  367. throws KeyStoreException
  368. {
  369. if (!initialized) {
  370. throw new KeyStoreException("Uninitialized keystore");
  371. }
  372. if ((key instanceof PrivateKey) && (chain==null || chain.length==0)) {
  373. throw new IllegalArgumentException("Private key must be "
  374. + "accompanied by certificate "
  375. + "chain");
  376. }
  377. keyStoreSpi.engineSetKeyEntry(alias, key, password, chain);
  378. }
  379. /**
  380. * Assigns the given key (that has already been protected) to the given
  381. * alias.
  382. *
  383. * <p>If the protected key is of type
  384. * <code>java.security.PrivateKey</code>, it must be accompanied by a
  385. * certificate chain certifying the corresponding public key. If the
  386. * underlying keystore implementation is of type <code>jks</code>,
  387. * <code>key</code> must be encoded as an
  388. * <code>EncryptedPrivateKeyInfo</code> as defined in the PKCS #8 standard.
  389. *
  390. * <p>If the given alias already exists, the keystore information
  391. * associated with it is overridden by the given key (and possibly
  392. * certificate chain).
  393. *
  394. * @param alias the alias name
  395. * @param key the key (in protected format) to be associated with the alias
  396. * @param chain the certificate chain for the corresponding public
  397. * key (only useful if the protected key is of type
  398. * <code>java.security.PrivateKey</code>).
  399. *
  400. * @exception KeyStoreException if the keystore has not been initialized
  401. * (loaded), or if this operation fails for some other reason.
  402. */
  403. public final void setKeyEntry(String alias, byte[] key,
  404. Certificate[] chain)
  405. throws KeyStoreException
  406. {
  407. if (!initialized) {
  408. throw new KeyStoreException("Uninitialized keystore");
  409. }
  410. keyStoreSpi.engineSetKeyEntry(alias, key, chain);
  411. }
  412. /**
  413. * Assigns the given certificate to the given alias.
  414. *
  415. * <p>If the given alias already exists in this keystore and identifies a
  416. * <i>trusted certificate entry</i>, the certificate associated with it is
  417. * overridden by the given certificate.
  418. *
  419. * @param alias the alias name
  420. * @param cert the certificate
  421. *
  422. * @exception KeyStoreException if the keystore has not been initialized,
  423. * or the given alias already exists and does not identify a
  424. * <i>trusted certificate entry</i>, or this operation fails for some
  425. * other reason.
  426. */
  427. public final void setCertificateEntry(String alias, Certificate cert)
  428. throws KeyStoreException
  429. {
  430. if (!initialized) {
  431. throw new KeyStoreException("Uninitialized keystore");
  432. }
  433. keyStoreSpi.engineSetCertificateEntry(alias, cert);
  434. }
  435. /**
  436. * Deletes the entry identified by the given alias from this keystore.
  437. *
  438. * @param alias the alias name
  439. *
  440. * @exception KeyStoreException if the keystore has not been initialized,
  441. * or if the entry cannot be removed.
  442. */
  443. public final void deleteEntry(String alias)
  444. throws KeyStoreException
  445. {
  446. if (!initialized) {
  447. throw new KeyStoreException("Uninitialized keystore");
  448. }
  449. keyStoreSpi.engineDeleteEntry(alias);
  450. }
  451. /**
  452. * Lists all the alias names of this keystore.
  453. *
  454. * @return enumeration of the alias names
  455. *
  456. * @exception KeyStoreException if the keystore has not been initialized
  457. * (loaded).
  458. */
  459. public final Enumeration aliases()
  460. throws KeyStoreException
  461. {
  462. if (!initialized) {
  463. throw new KeyStoreException("Uninitialized keystore");
  464. }
  465. return keyStoreSpi.engineAliases();
  466. }
  467. /**
  468. * Checks if the given alias exists in this keystore.
  469. *
  470. * @param alias the alias name
  471. *
  472. * @return true if the alias exists, false otherwise
  473. *
  474. * @exception KeyStoreException if the keystore has not been initialized
  475. * (loaded).
  476. */
  477. public final boolean containsAlias(String alias)
  478. throws KeyStoreException
  479. {
  480. if (!initialized) {
  481. throw new KeyStoreException("Uninitialized keystore");
  482. }
  483. return keyStoreSpi.engineContainsAlias(alias);
  484. }
  485. /**
  486. * Retrieves the number of entries in this keystore.
  487. *
  488. * @return the number of entries in this keystore
  489. *
  490. * @exception KeyStoreException if the keystore has not been initialized
  491. * (loaded).
  492. */
  493. public final int size()
  494. throws KeyStoreException
  495. {
  496. if (!initialized) {
  497. throw new KeyStoreException("Uninitialized keystore");
  498. }
  499. return keyStoreSpi.engineSize();
  500. }
  501. /**
  502. * Returns true if the entry identified by the given alias is a
  503. * <i>key entry</i>, and false otherwise.
  504. *
  505. * @param alias the alias for the keystore entry to be checked
  506. *
  507. * @return true if the entry identified by the given alias is a
  508. * <i>key entry</i>, false otherwise.
  509. *
  510. * @exception KeyStoreException if the keystore has not been initialized
  511. * (loaded).
  512. */
  513. public final boolean isKeyEntry(String alias)
  514. throws KeyStoreException
  515. {
  516. if (!initialized) {
  517. throw new KeyStoreException("Uninitialized keystore");
  518. }
  519. return keyStoreSpi.engineIsKeyEntry(alias);
  520. }
  521. /**
  522. * Returns true if the entry identified by the given alias is a
  523. * <i>trusted certificate entry</i>, and false otherwise.
  524. *
  525. * @param alias the alias for the keystore entry to be checked
  526. *
  527. * @return true if the entry identified by the given alias is a
  528. * <i>trusted certificate entry</i>, false otherwise.
  529. *
  530. * @exception KeyStoreException if the keystore has not been initialized
  531. * (loaded).
  532. */
  533. public final boolean isCertificateEntry(String alias)
  534. throws KeyStoreException
  535. {
  536. if (!initialized) {
  537. throw new KeyStoreException("Uninitialized keystore");
  538. }
  539. return keyStoreSpi.engineIsCertificateEntry(alias);
  540. }
  541. /**
  542. * Returns the (alias) name of the first keystore entry whose certificate
  543. * matches the given certificate.
  544. *
  545. * <p>This method attempts to match the given certificate with each
  546. * keystore entry. If the entry being considered
  547. * is a <i>trusted certificate entry</i>, the given certificate is
  548. * compared to that entry's certificate. If the entry being considered is
  549. * a <i>key entry</i>, the given certificate is compared to the first
  550. * element of that entry's certificate chain (if a chain exists).
  551. *
  552. * @param cert the certificate to match with.
  553. *
  554. * @return the (alias) name of the first entry with matching certificate,
  555. * or null if no such entry exists in this keystore.
  556. *
  557. * @exception KeyStoreException if the keystore has not been initialized
  558. * (loaded).
  559. */
  560. public final String getCertificateAlias(Certificate cert)
  561. throws KeyStoreException
  562. {
  563. if (!initialized) {
  564. throw new KeyStoreException("Uninitialized keystore");
  565. }
  566. return keyStoreSpi.engineGetCertificateAlias(cert);
  567. }
  568. /**
  569. * Stores this keystore to the given output stream, and protects its
  570. * integrity with the given password.
  571. *
  572. * @param stream the output stream to which this keystore is written.
  573. * @param password the password to generate the keystore integrity check
  574. *
  575. * @exception KeyStoreException if the keystore has not been initialized
  576. * (loaded).
  577. * @exception IOException if there was an I/O problem with data
  578. * @exception NoSuchAlgorithmException if the appropriate data integrity
  579. * algorithm could not be found
  580. * @exception CertificateException if any of the certificates included in
  581. * the keystore data could not be stored
  582. */
  583. public final void store(OutputStream stream, char[] password)
  584. throws KeyStoreException, IOException, NoSuchAlgorithmException,
  585. CertificateException
  586. {
  587. if (!initialized) {
  588. throw new KeyStoreException("Uninitialized keystore");
  589. }
  590. keyStoreSpi.engineStore(stream, password);
  591. }
  592. /**
  593. * Loads this KeyStore from the given input stream.
  594. *
  595. * <p>If a password is given, it is used to check the integrity of the
  596. * keystore data. Otherwise, the integrity of the keystore is not checked.
  597. *
  598. * <p>In order to create an empty keystore, or if the keystore cannot
  599. * be initialized from a stream (e.g., because it is stored on a hardware
  600. * token device), you pass <code>null</code>
  601. * as the <code>stream</code> argument.
  602. *
  603. * <p> Note that if this KeyStore has already been loaded, it is
  604. * reinitialized and loaded again from the given input stream.
  605. *
  606. * @param stream the input stream from which the keystore is loaded, or
  607. * null if an empty keystore is to be created.
  608. * @param password the (optional) password used to check the integrity of
  609. * the keystore.
  610. *
  611. * @exception IOException if there is an I/O or format problem with the
  612. * keystore data
  613. * @exception NoSuchAlgorithmException if the algorithm used to check
  614. * the integrity of the keystore cannot be found
  615. * @exception CertificateException if any of the certificates in the
  616. * keystore could not be loaded
  617. */
  618. public final void load(InputStream stream, char[] password)
  619. throws IOException, NoSuchAlgorithmException, CertificateException
  620. {
  621. keyStoreSpi.engineLoad(stream, password);
  622. initialized = true;
  623. }
  624. /**
  625. * Returns the default keystore type as specified in the Java security
  626. * properties file, or the string "jks" (acronym for "Java keystore")
  627. * if no such property exists.
  628. * The Java security properties file is located in the file named
  629. * <JAVA_HOME>/lib/security/java.security, where <JAVA_HOME>
  630. * refers to the directory where the SDK was installed.
  631. *
  632. * <p>The default keystore type can be used by applications that do not
  633. * want to use a hard-coded keystore type when calling one of the
  634. * <code>getInstance</code> methods, and want to provide a default keystore
  635. * type in case a user does not specify its own.
  636. *
  637. * <p>The default keystore type can be changed by setting the value of the
  638. * "keystore.type" security property (in the Java security properties
  639. * file) to the desired keystore type.
  640. *
  641. * @return the default keystore type as specified in the
  642. * Java security properties file, or the string "jks"
  643. * if no such property exists.
  644. */
  645. public final static String getDefaultType() {
  646. String kstype;
  647. kstype = (String)AccessController.doPrivileged(new PrivilegedAction() {
  648. public Object run() {
  649. return Security.getProperty(KEYSTORE_TYPE);
  650. }
  651. });
  652. if (kstype == null) {
  653. kstype = "jks";
  654. }
  655. return kstype;
  656. }
  657. }