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