001 /*
002 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package java.security;
027
028 import java.util.*;
029
030 import java.security.spec.AlgorithmParameterSpec;
031
032 import java.security.Provider.Service;
033
034 import sun.security.jca.*;
035 import sun.security.jca.GetInstance.Instance;
036
037 /**
038 * The KeyPairGenerator class is used to generate pairs of
039 * public and private keys. Key pair generators are constructed using the
040 * <code>getInstance</code> factory methods (static methods that
041 * return instances of a given class).
042 *
043 * <p>A Key pair generator for a particular algorithm creates a public/private
044 * key pair that can be used with this algorithm. It also associates
045 * algorithm-specific parameters with each of the generated keys.
046 *
047 * <p>There are two ways to generate a key pair: in an algorithm-independent
048 * manner, and in an algorithm-specific manner.
049 * The only difference between the two is the initialization of the object:
050 *
051 * <ul>
052 * <li><b>Algorithm-Independent Initialization</b>
053 * <p>All key pair generators share the concepts of a keysize and a
054 * source of randomness. The keysize is interpreted differently for different
055 * algorithms (e.g., in the case of the <i>DSA</i> algorithm, the keysize
056 * corresponds to the length of the modulus).
057 * There is an
058 * {@link #initialize(int, java.security.SecureRandom) initialize}
059 * method in this KeyPairGenerator class that takes these two universally
060 * shared types of arguments. There is also one that takes just a
061 * <code>keysize</code> argument, and uses the <code>SecureRandom</code>
062 * implementation of the highest-priority installed provider as the source
063 * of randomness. (If none of the installed providers supply an implementation
064 * of <code>SecureRandom</code>, a system-provided source of randomness is
065 * used.)
066 *
067 * <p>Since no other parameters are specified when you call the above
068 * algorithm-independent <code>initialize</code> methods, it is up to the
069 * provider what to do about the algorithm-specific parameters (if any) to be
070 * associated with each of the keys.
071 *
072 * <p>If the algorithm is the <i>DSA</i> algorithm, and the keysize (modulus
073 * size) is 512, 768, or 1024, then the <i>Sun</i> provider uses a set of
074 * precomputed values for the <code>p</code>, <code>q</code>, and
075 * <code>g</code> parameters. If the modulus size is not one of the above
076 * values, the <i>Sun</i> provider creates a new set of parameters. Other
077 * providers might have precomputed parameter sets for more than just the
078 * three modulus sizes mentioned above. Still others might not have a list of
079 * precomputed parameters at all and instead always create new parameter sets.
080 * <p>
081 *
082 * <li><b>Algorithm-Specific Initialization</b>
083 * <p>For situations where a set of algorithm-specific parameters already
084 * exists (e.g., so-called <i>community parameters</i> in DSA), there are two
085 * {@link #initialize(java.security.spec.AlgorithmParameterSpec)
086 * initialize} methods that have an <code>AlgorithmParameterSpec</code>
087 * argument. One also has a <code>SecureRandom</code> argument, while the
088 * the other uses the <code>SecureRandom</code>
089 * implementation of the highest-priority installed provider as the source
090 * of randomness. (If none of the installed providers supply an implementation
091 * of <code>SecureRandom</code>, a system-provided source of randomness is
092 * used.)
093 * </ul>
094 *
095 * <p>In case the client does not explicitly initialize the KeyPairGenerator
096 * (via a call to an <code>initialize</code> method), each provider must
097 * supply (and document) a default initialization.
098 * For example, the <i>Sun</i> provider uses a default modulus size (keysize)
099 * 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 * @version 1.65, 05/05/07
111 *
112 * @see java.security.spec.AlgorithmParameterSpec
113 */
114
115 public abstract class KeyPairGenerator extends KeyPairGeneratorSpi {
116
117 private final String algorithm;
118
119 // The provider
120 Provider provider;
121
122 /**
123 * Creates a KeyPairGenerator object for the specified algorithm.
124 *
125 * @param algorithm the standard string name of the algorithm.
126 * See Appendix A in the <a href=
127 * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
128 * Java Cryptography Architecture API Specification & Reference </a>
129 * for information about standard algorithm names.
130 */
131 protected KeyPairGenerator(String algorithm) {
132 this .algorithm = algorithm;
133 }
134
135 /**
136 * Returns the standard name of the algorithm for this key pair generator.
137 * See Appendix A in the <a href=
138 * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
139 * Java Cryptography Architecture API Specification & Reference </a>
140 * for information about standard algorithm names.
141 *
142 * @return the standard string name of the algorithm.
143 */
144 public String getAlgorithm() {
145 return this .algorithm;
146 }
147
148 private static KeyPairGenerator getInstance(Instance instance,
149 String algorithm) {
150 KeyPairGenerator kpg;
151 if (instance.impl instanceof KeyPairGenerator) {
152 kpg = (KeyPairGenerator) instance.impl;
153 } else {
154 KeyPairGeneratorSpi spi = (KeyPairGeneratorSpi) instance.impl;
155 kpg = new Delegate(spi, algorithm);
156 }
157 kpg.provider = instance.provider;
158 return kpg;
159 }
160
161 /**
162 * Returns a KeyPairGenerator object that generates public/private
163 * key pairs for the specified algorithm.
164 *
165 * <p> This method traverses the list of registered security Providers,
166 * starting with the most preferred Provider.
167 * A new KeyPairGenerator object encapsulating the
168 * KeyPairGeneratorSpi implementation from the first
169 * Provider that supports the specified algorithm is returned.
170 *
171 * <p> Note that the list of registered providers may be retrieved via
172 * the {@link Security#getProviders() Security.getProviders()} method.
173 *
174 * @param algorithm the standard string name of the algorithm.
175 * See Appendix A in the <a href=
176 * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
177 * Java Cryptography Architecture API Specification & Reference </a>
178 * for information about standard algorithm names.
179 *
180 * @return the new KeyPairGenerator object.
181 *
182 * @exception NoSuchAlgorithmException if no Provider supports a
183 * KeyPairGeneratorSpi implementation for the
184 * specified algorithm.
185 *
186 * @see Provider
187 */
188 public static KeyPairGenerator getInstance(String algorithm)
189 throws NoSuchAlgorithmException {
190 List<Service> list = GetInstance.getServices(
191 "KeyPairGenerator", algorithm);
192 Iterator<Service> t = list.iterator();
193 if (t.hasNext() == false) {
194 throw new NoSuchAlgorithmException(algorithm
195 + " KeyPairGenerator not available");
196 }
197 // find a working Spi or KeyPairGenerator subclass
198 NoSuchAlgorithmException failure = null;
199 do {
200 Service s = t.next();
201 try {
202 Instance instance = GetInstance.getInstance(s,
203 KeyPairGeneratorSpi.class);
204 if (instance.impl instanceof KeyPairGenerator) {
205 return getInstance(instance, algorithm);
206 } else {
207 return new Delegate(instance, t, algorithm);
208 }
209 } catch (NoSuchAlgorithmException e) {
210 if (failure == null) {
211 failure = e;
212 }
213 }
214 } while (t.hasNext());
215 throw failure;
216 }
217
218 /**
219 * Returns a KeyPairGenerator object that generates public/private
220 * key pairs for the specified algorithm.
221 *
222 * <p> A new KeyPairGenerator object encapsulating the
223 * KeyPairGeneratorSpi implementation from the specified provider
224 * is returned. The specified provider must be registered
225 * in the security provider list.
226 *
227 * <p> Note that the list of registered providers may be retrieved via
228 * the {@link Security#getProviders() Security.getProviders()} method.
229 *
230 * @param algorithm the standard string name of the algorithm.
231 * See Appendix A in the <a href=
232 * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
233 * Java Cryptography Architecture API Specification & Reference </a>
234 * for information about standard algorithm names.
235 *
236 * @param provider the string name of the provider.
237 *
238 * @return the new KeyPairGenerator object.
239 *
240 * @exception NoSuchAlgorithmException if a KeyPairGeneratorSpi
241 * implementation for the specified algorithm is not
242 * available from the specified provider.
243 *
244 * @exception NoSuchProviderException if the specified provider is not
245 * registered in the security provider list.
246 *
247 * @exception IllegalArgumentException if the provider name is null
248 * or empty.
249 *
250 * @see Provider
251 */
252 public static KeyPairGenerator getInstance(String algorithm,
253 String provider) throws NoSuchAlgorithmException,
254 NoSuchProviderException {
255 Instance instance = GetInstance.getInstance("KeyPairGenerator",
256 KeyPairGeneratorSpi.class, algorithm, provider);
257 return getInstance(instance, algorithm);
258 }
259
260 /**
261 * Returns a KeyPairGenerator object that generates public/private
262 * key pairs for the specified algorithm.
263 *
264 * <p> A new KeyPairGenerator object encapsulating the
265 * KeyPairGeneratorSpi implementation from the specified Provider
266 * object is returned. Note that the specified Provider object
267 * does not have to be registered in the provider list.
268 *
269 * @param algorithm the standard string name of the algorithm.
270 * See Appendix A in the <a href=
271 * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
272 * Java Cryptography Architecture API Specification & Reference </a>
273 * for information about standard algorithm names.
274 *
275 * @param provider the provider.
276 *
277 * @return the new KeyPairGenerator object.
278 *
279 * @exception NoSuchAlgorithmException if a KeyPairGeneratorSpi
280 * implementation for the specified algorithm is not available
281 * from the specified Provider object.
282 *
283 * @exception IllegalArgumentException if the specified provider is null.
284 *
285 * @see Provider
286 *
287 * @since 1.4
288 */
289 public static KeyPairGenerator getInstance(String algorithm,
290 Provider provider) throws NoSuchAlgorithmException {
291 Instance instance = GetInstance.getInstance("KeyPairGenerator",
292 KeyPairGeneratorSpi.class, algorithm, provider);
293 return getInstance(instance, algorithm);
294 }
295
296 /**
297 * Returns the provider of this key pair generator object.
298 *
299 * @return the provider of this key pair generator object
300 */
301 public final Provider getProvider() {
302 disableFailover();
303 return this .provider;
304 }
305
306 void disableFailover() {
307 // empty, overridden in Delegate
308 }
309
310 /**
311 * Initializes the key pair generator for a certain keysize using
312 * a default parameter set and the <code>SecureRandom</code>
313 * implementation of the highest-priority installed provider as the source
314 * of randomness.
315 * (If none of the installed providers supply an implementation of
316 * <code>SecureRandom</code>, a system-provided source of randomness is
317 * used.)
318 *
319 * @param keysize the keysize. This is an
320 * algorithm-specific metric, such as modulus length, specified in
321 * number of bits.
322 *
323 * @exception InvalidParameterException if the <code>keysize</code> is not
324 * supported by this KeyPairGenerator object.
325 */
326 public void initialize(int keysize) {
327 initialize(keysize, JCAUtil.getSecureRandom());
328 }
329
330 /**
331 * Initializes the key pair generator for a certain keysize with
332 * the given source of randomness (and a default parameter set).
333 *
334 * @param keysize the keysize. This is an
335 * algorithm-specific metric, such as modulus length, specified in
336 * number of bits.
337 * @param random the source of randomness.
338 *
339 * @exception InvalidParameterException if the <code>keysize</code> is not
340 * supported by this KeyPairGenerator object.
341 *
342 * @since 1.2
343 */
344 public void initialize(int keysize, SecureRandom random) {
345 // This does nothing, because either
346 // 1. the implementation object returned by getInstance() is an
347 // instance of KeyPairGenerator which has its own
348 // initialize(keysize, random) method, so the application would
349 // be calling that method directly, or
350 // 2. the implementation returned by getInstance() is an instance
351 // of Delegate, in which case initialize(keysize, random) is
352 // overridden to call the corresponding SPI method.
353 // (This is a special case, because the API and SPI method have the
354 // same name.)
355 }
356
357 /**
358 * Initializes the key pair generator using the specified parameter
359 * set and the <code>SecureRandom</code>
360 * implementation of the highest-priority installed provider as the source
361 * of randomness.
362 * (If none of the installed providers supply an implementation of
363 * <code>SecureRandom</code>, a system-provided source of randomness is
364 * used.).
365 *
366 * <p>This concrete method has been added to this previously-defined
367 * abstract class.
368 * This method calls the KeyPairGeneratorSpi
369 * {@link KeyPairGeneratorSpi#initialize(
370 * java.security.spec.AlgorithmParameterSpec,
371 * java.security.SecureRandom) initialize} method,
372 * passing it <code>params</code> and a source of randomness (obtained
373 * from the highest-priority installed provider or system-provided if none
374 * of the installed providers supply one).
375 * That <code>initialize</code> method always throws an
376 * UnsupportedOperationException if it is not overridden by the provider.
377 *
378 * @param params the parameter set used to generate the keys.
379 *
380 * @exception InvalidAlgorithmParameterException if the given parameters
381 * are inappropriate for this key pair generator.
382 *
383 * @since 1.2
384 */
385 public void initialize(AlgorithmParameterSpec params)
386 throws InvalidAlgorithmParameterException {
387 initialize(params, JCAUtil.getSecureRandom());
388 }
389
390 /**
391 * Initializes the key pair generator with the given parameter
392 * set and source of randomness.
393 *
394 * <p>This concrete method has been added to this previously-defined
395 * abstract class.
396 * This method calls the KeyPairGeneratorSpi {@link
397 * KeyPairGeneratorSpi#initialize(
398 * java.security.spec.AlgorithmParameterSpec,
399 * java.security.SecureRandom) initialize} method,
400 * passing it <code>params</code> and <code>random</code>.
401 * That <code>initialize</code>
402 * method always throws an
403 * UnsupportedOperationException if it is not overridden by the provider.
404 *
405 * @param params the parameter set used to generate the keys.
406 * @param random the source of randomness.
407 *
408 * @exception InvalidAlgorithmParameterException if the given parameters
409 * are inappropriate for this key pair generator.
410 *
411 * @since 1.2
412 */
413 public void initialize(AlgorithmParameterSpec params,
414 SecureRandom random)
415 throws InvalidAlgorithmParameterException {
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 * The following class allows providers to extend from KeyPairGeneratorSpi
481 * rather than from KeyPairGenerator. It represents a KeyPairGenerator
482 * with an encapsulated, provider-supplied SPI object (of type
483 * KeyPairGeneratorSpi).
484 * If the provider implementation is an instance of KeyPairGeneratorSpi,
485 * the getInstance() methods above return an instance of this class, with
486 * the SPI object encapsulated.
487 *
488 * Note: All SPI methods from the original KeyPairGenerator class have been
489 * moved up the hierarchy into a new class (KeyPairGeneratorSpi), which has
490 * been interposed in the hierarchy between the API (KeyPairGenerator)
491 * and its original parent (Object).
492 */
493
494 //
495 // error failover notes:
496 //
497 // . we failover if the implementation throws an error during init
498 // by retrying the init on other providers
499 //
500 // . we also failover if the init succeeded but the subsequent call
501 // to generateKeyPair() fails. In order for this to work, we need
502 // to remember the parameters to the last successful call to init
503 // and initialize() the next spi using them.
504 //
505 // . although not specified, KeyPairGenerators could be thread safe,
506 // so we make sure we do not interfere with that
507 //
508 // . failover is not available, if:
509 // . getInstance(algorithm, provider) was used
510 // . a provider extends KeyPairGenerator rather than
511 // KeyPairGeneratorSpi (JDK 1.1 style)
512 // . once getProvider() is called
513 //
514 private static final class Delegate extends KeyPairGenerator {
515
516 // The provider implementation (delegate)
517 private volatile KeyPairGeneratorSpi spi;
518
519 private final Object lock = new Object();
520
521 private Iterator<Service> serviceIterator;
522
523 private final static int I_NONE = 1;
524 private final static int I_SIZE = 2;
525 private final static int I_PARAMS = 3;
526
527 private int initType;
528 private int initKeySize;
529 private AlgorithmParameterSpec initParams;
530 private SecureRandom initRandom;
531
532 // constructor
533 Delegate(KeyPairGeneratorSpi spi, String algorithm) {
534 super (algorithm);
535 this .spi = spi;
536 }
537
538 Delegate(Instance instance, Iterator<Service> serviceIterator,
539 String algorithm) {
540 super (algorithm);
541 spi = (KeyPairGeneratorSpi) instance.impl;
542 provider = instance.provider;
543 this .serviceIterator = serviceIterator;
544 initType = I_NONE;
545 }
546
547 /**
548 * Update the active spi of this class and return the next
549 * implementation for failover. If no more implemenations are
550 * available, this method returns null. However, the active spi of
551 * this class is never set to null.
552 */
553 private KeyPairGeneratorSpi nextSpi(KeyPairGeneratorSpi oldSpi,
554 boolean reinit) {
555 synchronized (lock) {
556 // somebody else did a failover concurrently
557 // try that spi now
558 if ((oldSpi != null) && (oldSpi != spi)) {
559 return spi;
560 }
561 if (serviceIterator == null) {
562 return null;
563 }
564 while (serviceIterator.hasNext()) {
565 Service s = serviceIterator.next();
566 try {
567 Object inst = s.newInstance(null);
568 // ignore non-spis
569 if (inst instanceof KeyPairGeneratorSpi == false) {
570 continue;
571 }
572 if (inst instanceof KeyPairGenerator) {
573 continue;
574 }
575 KeyPairGeneratorSpi spi = (KeyPairGeneratorSpi) inst;
576 if (reinit) {
577 if (initType == I_SIZE) {
578 spi.initialize(initKeySize, initRandom);
579 } else if (initType == I_PARAMS) {
580 spi.initialize(initParams, initRandom);
581 } else if (initType != I_NONE) {
582 throw new AssertionError(
583 "KeyPairGenerator initType: "
584 + initType);
585 }
586 }
587 provider = s.getProvider();
588 this .spi = spi;
589 return spi;
590 } catch (Exception e) {
591 // ignore
592 }
593 }
594 disableFailover();
595 return null;
596 }
597 }
598
599 void disableFailover() {
600 serviceIterator = null;
601 initType = 0;
602 initParams = null;
603 initRandom = null;
604 }
605
606 // engine method
607 public void initialize(int keysize, SecureRandom random) {
608 if (serviceIterator == null) {
609 spi.initialize(keysize, random);
610 return;
611 }
612 RuntimeException failure = null;
613 KeyPairGeneratorSpi mySpi = spi;
614 do {
615 try {
616 mySpi.initialize(keysize, random);
617 initType = I_SIZE;
618 initKeySize = keysize;
619 initParams = null;
620 initRandom = random;
621 return;
622 } catch (RuntimeException e) {
623 if (failure == null) {
624 failure = e;
625 }
626 mySpi = nextSpi(mySpi, false);
627 }
628 } while (mySpi != null);
629 throw failure;
630 }
631
632 // engine method
633 public void initialize(AlgorithmParameterSpec params,
634 SecureRandom random)
635 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 }
|