1. /*
  2. * @(#)KeyPairGenerator.java 1.56 04/01/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.util.*;
  9. import java.security.spec.AlgorithmParameterSpec;
  10. import java.security.Provider.Service;
  11. import sun.security.jca.*;
  12. import sun.security.jca.GetInstance.Instance;
  13. /**
  14. * The KeyPairGenerator class is used to generate pairs of
  15. * public and private keys. Key pair generators are constructed using the
  16. * <code>getInstance</code> factory methods (static methods that
  17. * return instances of a given class).
  18. *
  19. * <p>A Key pair generator for a particular algorithm creates a public/private
  20. * key pair that can be used with this algorithm. It also associates
  21. * algorithm-specific parameters with each of the generated keys.
  22. *
  23. * <p>There are two ways to generate a key pair: in an algorithm-independent
  24. * manner, and in an algorithm-specific manner.
  25. * The only difference between the two is the initialization of the object:
  26. *
  27. * <ul>
  28. * <li><b>Algorithm-Independent Initialization</b>
  29. * <p>All key pair generators share the concepts of a keysize and a
  30. * source of randomness. The keysize is interpreted differently for different
  31. * algorithms (e.g., in the case of the <i>DSA</i> algorithm, the keysize
  32. * corresponds to the length of the modulus).
  33. * There is an
  34. * {@link #initialize(int, java.security.SecureRandom) initialize}
  35. * method in this KeyPairGenerator class that takes these two universally
  36. * shared types of arguments. There is also one that takes just a
  37. * <code>keysize</code> argument, and uses the <code>SecureRandom</code>
  38. * implementation of the highest-priority installed provider as the source
  39. * of randomness. (If none of the installed providers supply an implementation
  40. * of <code>SecureRandom</code>, a system-provided source of randomness is
  41. * used.)
  42. *
  43. * <p>Since no other parameters are specified when you call the above
  44. * algorithm-independent <code>initialize</code> methods, it is up to the
  45. * provider what to do about the algorithm-specific parameters (if any) to be
  46. * associated with each of the keys.
  47. *
  48. * <p>If the algorithm is the <i>DSA</i> algorithm, and the keysize (modulus
  49. * size) is 512, 768, or 1024, then the <i>Sun</i> provider uses a set of
  50. * precomputed values for the <code>p</code>, <code>q</code>, and
  51. * <code>g</code> parameters. If the modulus size is not one of the above
  52. * values, the <i>Sun</i> provider creates a new set of parameters. Other
  53. * providers might have precomputed parameter sets for more than just the
  54. * three modulus sizes mentioned above. Still others might not have a list of
  55. * precomputed parameters at all and instead always create new parameter sets.
  56. * <p>
  57. *
  58. * <li><b>Algorithm-Specific Initialization</b>
  59. * <p>For situations where a set of algorithm-specific parameters already
  60. * exists (e.g., so-called <i>community parameters</i> in DSA), there are two
  61. * {@link #initialize(java.security.spec.AlgorithmParameterSpec)
  62. * initialize} methods that have an <code>AlgorithmParameterSpec</code>
  63. * argument. One also has a <code>SecureRandom</code> argument, while the
  64. * the other uses the <code>SecureRandom</code>
  65. * implementation of the highest-priority installed provider as the source
  66. * of randomness. (If none of the installed providers supply an implementation
  67. * of <code>SecureRandom</code>, a system-provided source of randomness is
  68. * used.)
  69. * </ul>
  70. *
  71. * <p>In case the client does not explicitly initialize the KeyPairGenerator
  72. * (via a call to an <code>initialize</code> method), each provider must
  73. * supply (and document) a default initialization.
  74. * For example, the <i>Sun</i> provider uses a default modulus size (keysize)
  75. * of 1024 bits.
  76. *
  77. * <p>Note that this class is abstract and extends from
  78. * <code>KeyPairGeneratorSpi</code> for historical reasons.
  79. * Application developers should only take notice of the methods defined in
  80. * this <code>KeyPairGenerator</code> class; all the methods in
  81. * the superclass are intended for cryptographic service providers who wish to
  82. * supply their own implementations of key pair generators.
  83. *
  84. * @author Benjamin Renaud
  85. *
  86. * @version 1.56, 01/28/04
  87. *
  88. * @see java.security.spec.AlgorithmParameterSpec
  89. */
  90. public abstract class KeyPairGenerator extends KeyPairGeneratorSpi {
  91. private final String algorithm;
  92. // The provider
  93. Provider provider;
  94. /**
  95. * Creates a KeyPairGenerator object for the specified algorithm.
  96. *
  97. * @param algorithm the standard string name of the algorithm.
  98. * See Appendix A in the <a href=
  99. * "../../../guide/security/CryptoSpec.html#AppA">
  100. * Java Cryptography Architecture API Specification & Reference </a>
  101. * for information about standard algorithm names.
  102. */
  103. protected KeyPairGenerator(String algorithm) {
  104. this.algorithm = algorithm;
  105. }
  106. /**
  107. * Returns the standard name of the algorithm for this key pair generator.
  108. * See Appendix A in the <a href=
  109. * "../../../guide/security/CryptoSpec.html#AppA">
  110. * Java Cryptography Architecture API Specification & Reference </a>
  111. * for information about standard algorithm names.
  112. *
  113. * @return the standard string name of the algorithm.
  114. */
  115. public String getAlgorithm() {
  116. return this.algorithm;
  117. }
  118. private static KeyPairGenerator getInstance(Instance instance,
  119. String algorithm) {
  120. KeyPairGenerator kpg;
  121. if (instance.impl instanceof KeyPairGenerator) {
  122. kpg = (KeyPairGenerator)instance.impl;
  123. } else {
  124. KeyPairGeneratorSpi spi = (KeyPairGeneratorSpi)instance.impl;
  125. kpg = new Delegate(spi, algorithm);
  126. }
  127. kpg.provider = instance.provider;
  128. return kpg;
  129. }
  130. /**
  131. * Generates a KeyPairGenerator object that implements the specified digest
  132. * algorithm. If the default provider package
  133. * provides an implementation of the requested digest algorithm,
  134. * an instance of KeyPairGenerator containing that implementation is
  135. * returned.
  136. * If the algorithm is not available in the default
  137. * package, other packages are searched.
  138. *
  139. * @param algorithm the standard string name of the algorithm.
  140. * See Appendix A in the <a href=
  141. * "../../../guide/security/CryptoSpec.html#AppA">
  142. * Java Cryptography Architecture API Specification & Reference </a>
  143. * for information about standard algorithm names.
  144. *
  145. * @return the new KeyPairGenerator object.
  146. *
  147. * @exception NoSuchAlgorithmException if the algorithm is
  148. * not available in the environment.
  149. */
  150. public static KeyPairGenerator getInstance(String algorithm)
  151. throws NoSuchAlgorithmException {
  152. List<Service> list =
  153. GetInstance.getServices("KeyPairGenerator", algorithm);
  154. Iterator<Service> t = list.iterator();
  155. if (t.hasNext() == false) {
  156. throw new NoSuchAlgorithmException
  157. (algorithm + " KeyPairGenerator not available");
  158. }
  159. // find a working Spi or KeyPairGenerator subclass
  160. NoSuchAlgorithmException failure = null;
  161. do {
  162. Service s = t.next();
  163. try {
  164. Instance instance =
  165. GetInstance.getInstance(s, KeyPairGeneratorSpi.class);
  166. if (instance.impl instanceof KeyPairGenerator) {
  167. return getInstance(instance, algorithm);
  168. } else {
  169. return new Delegate(instance, t, algorithm);
  170. }
  171. } catch (NoSuchAlgorithmException e) {
  172. if (failure == null) {
  173. failure = e;
  174. }
  175. }
  176. } while (t.hasNext());
  177. throw failure;
  178. }
  179. /**
  180. * Generates a KeyPairGenerator object implementing the specified
  181. * algorithm, as supplied from the specified provider,
  182. * if such an algorithm is available from the provider.
  183. *
  184. * @param algorithm the standard string name of the algorithm.
  185. * See Appendix A in the <a href=
  186. * "../../../guide/security/CryptoSpec.html#AppA">
  187. * Java Cryptography Architecture API Specification & Reference </a>
  188. * for information about standard algorithm names.
  189. *
  190. * @param provider the string name of the provider.
  191. *
  192. * @return the new KeyPairGenerator object.
  193. *
  194. * @exception NoSuchAlgorithmException if the algorithm is
  195. * not available from the provider.
  196. *
  197. * @exception NoSuchProviderException if the provider is not
  198. * available in the environment.
  199. *
  200. * @exception IllegalArgumentException if the provider name is null
  201. * or empty.
  202. *
  203. * @see Provider
  204. */
  205. public static KeyPairGenerator getInstance(String algorithm,
  206. String provider)
  207. throws NoSuchAlgorithmException, NoSuchProviderException {
  208. Instance instance = GetInstance.getInstance("KeyPairGenerator",
  209. KeyPairGeneratorSpi.class, algorithm, provider);
  210. return getInstance(instance, algorithm);
  211. }
  212. /**
  213. * Generates a KeyPairGenerator object implementing the specified
  214. * algorithm, as supplied from the specified provider,
  215. * if such an algorithm is available from the provider.
  216. * Note: the <code>provider</code> doesn't have to be registered.
  217. *
  218. * @param algorithm the standard string name of the algorithm.
  219. * See Appendix A in the <a href=
  220. * "../../../guide/security/CryptoSpec.html#AppA">
  221. * Java Cryptography Architecture API Specification & Reference </a>
  222. * for information about standard algorithm names.
  223. *
  224. * @param provider the provider.
  225. *
  226. * @return the new KeyPairGenerator object.
  227. *
  228. * @exception NoSuchAlgorithmException if the algorithm is
  229. * not available from the provider.
  230. *
  231. * @exception IllegalArgumentException if the <code>provider</code> is
  232. * null.
  233. *
  234. * @see Provider
  235. *
  236. * @since 1.4
  237. */
  238. public static KeyPairGenerator getInstance(String algorithm,
  239. Provider provider) throws NoSuchAlgorithmException {
  240. Instance instance = GetInstance.getInstance("KeyPairGenerator",
  241. KeyPairGeneratorSpi.class, algorithm, provider);
  242. return getInstance(instance, algorithm);
  243. }
  244. /**
  245. * Returns the provider of this key pair generator object.
  246. *
  247. * @return the provider of this key pair generator object
  248. */
  249. public final Provider getProvider() {
  250. disableFailover();
  251. return this.provider;
  252. }
  253. void disableFailover() {
  254. // empty, overridden in Delegate
  255. }
  256. /**
  257. * Initializes the key pair generator for a certain keysize using
  258. * a default parameter set and the <code>SecureRandom</code>
  259. * implementation of the highest-priority installed provider as the source
  260. * of randomness.
  261. * (If none of the installed providers supply an implementation of
  262. * <code>SecureRandom</code>, a system-provided source of randomness is
  263. * used.)
  264. *
  265. * @param keysize the keysize. This is an
  266. * algorithm-specific metric, such as modulus length, specified in
  267. * number of bits.
  268. *
  269. * @exception InvalidParameterException if the <code>keysize</code> is not
  270. * supported by this KeyPairGenerator object.
  271. */
  272. public void initialize(int keysize) {
  273. initialize(keysize, JCAUtil.getSecureRandom());
  274. }
  275. /**
  276. * Initializes the key pair generator for a certain keysize with
  277. * the given source of randomness (and a default parameter set).
  278. *
  279. * @param keysize the keysize. This is an
  280. * algorithm-specific metric, such as modulus length, specified in
  281. * number of bits.
  282. * @param random the source of randomness.
  283. *
  284. * @exception InvalidParameterException if the <code>keysize</code> is not
  285. * supported by this KeyPairGenerator object.
  286. *
  287. * @since 1.2
  288. */
  289. public void initialize(int keysize, SecureRandom random) {
  290. // This does nothing, because either
  291. // 1. the implementation object returned by getInstance() is an
  292. // instance of KeyPairGenerator which has its own
  293. // initialize(keysize, random) method, so the application would
  294. // be calling that method directly, or
  295. // 2. the implementation returned by getInstance() is an instance
  296. // of Delegate, in which case initialize(keysize, random) is
  297. // overridden to call the corresponding SPI method.
  298. // (This is a special case, because the API and SPI method have the
  299. // same name.)
  300. }
  301. /**
  302. * Initializes the key pair generator using the specified parameter
  303. * set and the <code>SecureRandom</code>
  304. * implementation of the highest-priority installed provider as the source
  305. * of randomness.
  306. * (If none of the installed providers supply an implementation of
  307. * <code>SecureRandom</code>, a system-provided source of randomness is
  308. * used.).
  309. *
  310. * <p>This concrete method has been added to this previously-defined
  311. * abstract class.
  312. * This method calls the KeyPairGeneratorSpi
  313. * {@link KeyPairGeneratorSpi#initialize(
  314. * java.security.spec.AlgorithmParameterSpec,
  315. * java.security.SecureRandom) initialize} method,
  316. * passing it <code>params</code> and a source of randomness (obtained
  317. * from the highest-priority installed provider or system-provided if none
  318. * of the installed providers supply one).
  319. * That <code>initialize</code> method always throws an
  320. * UnsupportedOperationException if it is not overridden by the provider.
  321. *
  322. * @param params the parameter set used to generate the keys.
  323. *
  324. * @exception InvalidAlgorithmParameterException if the given parameters
  325. * are inappropriate for this key pair generator.
  326. *
  327. * @since 1.2
  328. */
  329. public void initialize(AlgorithmParameterSpec params)
  330. throws InvalidAlgorithmParameterException {
  331. initialize(params, JCAUtil.getSecureRandom());
  332. }
  333. /**
  334. * Initializes the key pair generator with the given parameter
  335. * set and source of randomness.
  336. *
  337. * <p>This concrete method has been added to this previously-defined
  338. * abstract class.
  339. * This method calls the KeyPairGeneratorSpi {@link
  340. * KeyPairGeneratorSpi#initialize(
  341. * java.security.spec.AlgorithmParameterSpec,
  342. * java.security.SecureRandom) initialize} method,
  343. * passing it <code>params</code> and <code>random</code>.
  344. * That <code>initialize</code>
  345. * method always throws an
  346. * UnsupportedOperationException if it is not overridden by the provider.
  347. *
  348. * @param params the parameter set used to generate the keys.
  349. * @param random the source of randomness.
  350. *
  351. * @exception InvalidAlgorithmParameterException if the given parameters
  352. * are inappropriate for this key pair generator.
  353. *
  354. * @since 1.2
  355. */
  356. public void initialize(AlgorithmParameterSpec params,
  357. SecureRandom random)
  358. throws InvalidAlgorithmParameterException
  359. {
  360. // This does nothing, because either
  361. // 1. the implementation object returned by getInstance() is an
  362. // instance of KeyPairGenerator which has its own
  363. // initialize(params, random) method, so the application would
  364. // be calling that method directly, or
  365. // 2. the implementation returned by getInstance() is an instance
  366. // of Delegate, in which case initialize(params, random) is
  367. // overridden to call the corresponding SPI method.
  368. // (This is a special case, because the API and SPI method have the
  369. // same name.)
  370. }
  371. /**
  372. * Generates a key pair.
  373. *
  374. * <p>If this KeyPairGenerator has not been initialized explicitly,
  375. * provider-specific defaults will be used for the size and other
  376. * (algorithm-specific) values of the generated keys.
  377. *
  378. * <p>This will generate a new key pair every time it is called.
  379. *
  380. * <p>This method is functionally equivalent to
  381. * {@link #generateKeyPair() generateKeyPair}.
  382. *
  383. * @return the generated key pair
  384. *
  385. * @since 1.2
  386. */
  387. public final KeyPair genKeyPair() {
  388. return generateKeyPair();
  389. }
  390. /**
  391. * Generates a key pair.
  392. *
  393. * <p>If this KeyPairGenerator has not been initialized explicitly,
  394. * provider-specific defaults will be used for the size and other
  395. * (algorithm-specific) values of the generated keys.
  396. *
  397. * <p>This will generate a new key pair every time it is called.
  398. *
  399. * <p>This method is functionally equivalent to
  400. * {@link #genKeyPair() genKeyPair}.
  401. *
  402. * @return the generated key pair
  403. */
  404. public KeyPair generateKeyPair() {
  405. // This does nothing (except returning null), because either:
  406. //
  407. // 1. the implementation object returned by getInstance() is an
  408. // instance of KeyPairGenerator which has its own implementation
  409. // of generateKeyPair (overriding this one), so the application
  410. // would be calling that method directly, or
  411. //
  412. // 2. the implementation returned by getInstance() is an instance
  413. // of Delegate, in which case generateKeyPair is
  414. // overridden to invoke the corresponding SPI method.
  415. //
  416. // (This is a special case, because in JDK 1.1.x the generateKeyPair
  417. // method was used both as an API and a SPI method.)
  418. return null;
  419. }
  420. /*
  421. * The following class allows providers to extend from KeyPairGeneratorSpi
  422. * rather than from KeyPairGenerator. It represents a KeyPairGenerator
  423. * with an encapsulated, provider-supplied SPI object (of type
  424. * KeyPairGeneratorSpi).
  425. * If the provider implementation is an instance of KeyPairGeneratorSpi,
  426. * the getInstance() methods above return an instance of this class, with
  427. * the SPI object encapsulated.
  428. *
  429. * Note: All SPI methods from the original KeyPairGenerator class have been
  430. * moved up the hierarchy into a new class (KeyPairGeneratorSpi), which has
  431. * been interposed in the hierarchy between the API (KeyPairGenerator)
  432. * and its original parent (Object).
  433. */
  434. //
  435. // error failover notes:
  436. //
  437. // . we failover if the implementation throws an error during init
  438. // by retrying the init on other providers
  439. //
  440. // . we also failover if the init succeeded but the subsequent call
  441. // to generateKeyPair() fails. In order for this to work, we need
  442. // to remember the parameters to the last successful call to init
  443. // and initialize() the next spi using them.
  444. //
  445. // . although not specified, KeyPairGenerators could be thread safe,
  446. // so we make sure we do not interfere with that
  447. //
  448. // . failover is not available, if:
  449. // . getInstance(algorithm, provider) was used
  450. // . a provider extends KeyPairGenerator rather than
  451. // KeyPairGeneratorSpi (JDK 1.1 style)
  452. // . once getProvider() is called
  453. //
  454. private static final class Delegate extends KeyPairGenerator {
  455. // The provider implementation (delegate)
  456. private volatile KeyPairGeneratorSpi spi;
  457. private final Object lock = new Object();
  458. private Iterator<Service> serviceIterator;
  459. private final static int I_NONE = 1;
  460. private final static int I_SIZE = 2;
  461. private final static int I_PARAMS = 3;
  462. private int initType;
  463. private int initKeySize;
  464. private AlgorithmParameterSpec initParams;
  465. private SecureRandom initRandom;
  466. // constructor
  467. Delegate(KeyPairGeneratorSpi spi, String algorithm) {
  468. super(algorithm);
  469. this.spi = spi;
  470. }
  471. Delegate(Instance instance, Iterator<Service> serviceIterator,
  472. String algorithm) {
  473. super(algorithm);
  474. spi = (KeyPairGeneratorSpi)instance.impl;
  475. provider = instance.provider;
  476. this.serviceIterator = serviceIterator;
  477. initType = I_NONE;
  478. }
  479. /**
  480. * Update the active spi of this class and return the next
  481. * implementation for failover. If no more implemenations are
  482. * available, this method returns null. However, the active spi of
  483. * this class is never set to null.
  484. */
  485. private KeyPairGeneratorSpi nextSpi(KeyPairGeneratorSpi oldSpi,
  486. boolean reinit) {
  487. synchronized (lock) {
  488. // somebody else did a failover concurrently
  489. // try that spi now
  490. if ((oldSpi != null) && (oldSpi != spi)) {
  491. return spi;
  492. }
  493. if (serviceIterator == null) {
  494. return null;
  495. }
  496. while (serviceIterator.hasNext()) {
  497. Service s = serviceIterator.next();
  498. try {
  499. Object inst = s.newInstance(null);
  500. // ignore non-spis
  501. if (inst instanceof KeyPairGeneratorSpi == false) {
  502. continue;
  503. }
  504. if (inst instanceof KeyPairGenerator) {
  505. continue;
  506. }
  507. KeyPairGeneratorSpi spi = (KeyPairGeneratorSpi)inst;
  508. if (reinit) {
  509. if (initType == I_SIZE) {
  510. spi.initialize(initKeySize, initRandom);
  511. } else if (initType == I_PARAMS) {
  512. spi.initialize(initParams, initRandom);
  513. } else if (initType != I_NONE) {
  514. throw new AssertionError
  515. ("KeyPairGenerator initType: " + initType);
  516. }
  517. }
  518. provider = s.getProvider();
  519. this.spi = spi;
  520. return spi;
  521. } catch (Exception e) {
  522. // ignore
  523. }
  524. }
  525. disableFailover();
  526. return null;
  527. }
  528. }
  529. void disableFailover() {
  530. serviceIterator = null;
  531. initType = 0;
  532. initParams = null;
  533. initRandom = null;
  534. }
  535. // engine method
  536. public void initialize(int keysize, SecureRandom random) {
  537. if (serviceIterator == null) {
  538. spi.initialize(keysize, random);
  539. return;
  540. }
  541. RuntimeException failure = null;
  542. KeyPairGeneratorSpi mySpi = spi;
  543. do {
  544. try {
  545. mySpi.initialize(keysize, random);
  546. initType = I_SIZE;
  547. initKeySize = keysize;
  548. initParams = null;
  549. initRandom = random;
  550. return;
  551. } catch (RuntimeException e) {
  552. if (failure == null) {
  553. failure = e;
  554. }
  555. mySpi = nextSpi(mySpi, false);
  556. }
  557. } while (mySpi != null);
  558. throw failure;
  559. }
  560. // engine method
  561. public void initialize(AlgorithmParameterSpec params,
  562. SecureRandom random) throws InvalidAlgorithmParameterException {
  563. if (serviceIterator == null) {
  564. spi.initialize(params, random);
  565. return;
  566. }
  567. Exception failure = null;
  568. KeyPairGeneratorSpi mySpi = spi;
  569. do {
  570. try {
  571. mySpi.initialize(params, random);
  572. initType = I_PARAMS;
  573. initKeySize = 0;
  574. initParams = params;
  575. initRandom = random;
  576. return;
  577. } catch (Exception e) {
  578. if (failure == null) {
  579. failure = e;
  580. }
  581. mySpi = nextSpi(mySpi, false);
  582. }
  583. } while (mySpi != null);
  584. if (failure instanceof RuntimeException) {
  585. throw (RuntimeException)failure;
  586. }
  587. // must be an InvalidAlgorithmParameterException
  588. throw (InvalidAlgorithmParameterException)failure;
  589. }
  590. // engine method
  591. public KeyPair generateKeyPair() {
  592. if (serviceIterator == null) {
  593. return spi.generateKeyPair();
  594. }
  595. RuntimeException failure = null;
  596. KeyPairGeneratorSpi mySpi = spi;
  597. do {
  598. try {
  599. return mySpi.generateKeyPair();
  600. } catch (RuntimeException e) {
  601. if (failure == null) {
  602. failure = e;
  603. }
  604. mySpi = nextSpi(mySpi, true);
  605. }
  606. } while (mySpi != null);
  607. throw failure;
  608. }
  609. }
  610. }