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