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