History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/crypto/KeyGenerator.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/crypto/KeyGenerator.java+540−0
@@ -0,0 +1,540 @@
1/*
2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package javax.crypto;
27
28import java.util.*;
29
30import java.security.*;
31import java.security.Provider.Service;
32import java.security.spec.*;
33
34import sun.security.jca.*;
35import sun.security.jca.GetInstance.Instance;
36
37/**
38 * This class provides the functionality of a secret (symmetric) key generator.
39 *
40 * <p>Key generators are constructed using one of the <code>getInstance</code>
41 * class methods of this class.
42 *
43 * <p>KeyGenerator objects are reusable, i.e., after a key has been
44 * generated, the same KeyGenerator object can be re-used to generate further
45 * keys.
46 *
47 * <p>There are two ways to generate a key: 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 generators share the concepts of a <i>keysize</i> and a
54 * <i>source of randomness</i>.
55 * There is an
56 * {@link #init(int, java.security.SecureRandom) init}
57 * method in this KeyGenerator class that takes these two universally
58 * shared types of arguments. There is also one that takes just a
59 * <code>keysize</code> argument, and uses the SecureRandom implementation
60 * of the highest-priority installed provider as the source of randomness
61 * (or a system-provided source of randomness if none of the installed
62 * providers supply a SecureRandom implementation), and one that takes just a
63 * source of randomness.
64 *
65 * <p>Since no other parameters are specified when you call the above
66 * algorithm-independent <code>init</code> methods, it is up to the
67 * provider what to do about the algorithm-specific parameters (if any) to be
68 * associated with each of the keys.
69 * <p>
70 *
71 * <li><b>Algorithm-Specific Initialization</b>
72 * <p>For situations where a set of algorithm-specific parameters already
73 * exists, there are two
74 * {@link #init(java.security.spec.AlgorithmParameterSpec) init}
75 * methods that have an <code>AlgorithmParameterSpec</code>
76 * argument. One also has a <code>SecureRandom</code> argument, while the
77 * other uses the SecureRandom implementation
78 * of the highest-priority installed provider as the source of randomness
79 * (or a system-provided source of randomness if none of the installed
80 * providers supply a SecureRandom implementation).
81 * </ul>
82 *
83 * <p>In case the client does not explicitly initialize the KeyGenerator
84 * (via a call to an <code>init</code> method), each provider must
85 * supply (and document) a default initialization.
86 *
87 * <p> Every implementation of the Java platform is required to support the
88 * following standard <code>KeyGenerator</code> algorithms with the keysizes in
89 * parentheses:
90 * <ul>
91 * <li><tt>AES</tt> (128)</li>
92 * <li><tt>DES</tt> (56)</li>
93 * <li><tt>DESede</tt> (168)</li>
94 * <li><tt>HmacSHA1</tt></li>
95 * <li><tt>HmacSHA256</tt></li>
96 * </ul>
97 * These algorithms are described in the <a href=
98 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator">
99 * KeyGenerator section</a> of the
100 * Java Cryptography Architecture Standard Algorithm Name Documentation.
101 * Consult the release documentation for your implementation to see if any
102 * other algorithms are supported.
103 *
104 * @author Jan Luehe
105 *
106 * @see SecretKey
107 * @since 1.4
108 */
109
110public class KeyGenerator {
111
112 // see java.security.KeyPairGenerator for failover notes
113
114 private final static int I_NONE = 1;
115 private final static int I_RANDOM = 2;
116 private final static int I_PARAMS = 3;
117 private final static int I_SIZE = 4;
118
119 // The provider
120 private Provider provider;
121
122 // The provider implementation (delegate)
123 private volatile KeyGeneratorSpi spi;
124
125 // The algorithm
126 private final String algorithm;
127
128 private final Object lock = new Object();
129
130 private Iterator serviceIterator;
131
132 private int initType;
133 private int initKeySize;
134 private AlgorithmParameterSpec initParams;
135 private SecureRandom initRandom;
136
137 /**
138 * Creates a KeyGenerator object.
139 *
140 * @param keyGenSpi the delegate
141 * @param provider the provider
142 * @param algorithm the algorithm
143 */
144 protected KeyGenerator(KeyGeneratorSpi keyGenSpi, Provider provider,
145 String algorithm) {
146 this.spi = keyGenSpi;
147 this.provider = provider;
148 this.algorithm = algorithm;
149 }
150
151 private KeyGenerator(String algorithm) throws NoSuchAlgorithmException {
152 this.algorithm = algorithm;
153 List list = GetInstance.getServices("KeyGenerator", algorithm);
154 serviceIterator = list.iterator();
155 initType = I_NONE;
156 // fetch and instantiate initial spi
157 if (nextSpi(null, false) == null) {
158 throw new NoSuchAlgorithmException
159 (algorithm + " KeyGenerator not available");
160 }
161 }
162
163 /**
164 * Returns the algorithm name of this <code>KeyGenerator</code> object.
165 *
166 * <p>This is the same name that was specified in one of the
167 * <code>getInstance</code> calls that created this
168 * <code>KeyGenerator</code> object.
169 *
170 * @return the algorithm name of this <code>KeyGenerator</code> object.
171 */
172 public final String getAlgorithm() {
173 return this.algorithm;
174 }
175
176 /**
177 * Returns a <code>KeyGenerator</code> object that generates secret keys
178 * for the specified algorithm.
179 *
180 * <p> This method traverses the list of registered security Providers,
181 * starting with the most preferred Provider.
182 * A new KeyGenerator object encapsulating the
183 * KeyGeneratorSpi implementation from the first
184 * Provider that supports the specified algorithm is returned.
185 *
186 * <p> Note that the list of registered providers may be retrieved via
187 * the {@link Security#getProviders() Security.getProviders()} method.
188 *
189 * @param algorithm the standard name of the requested key algorithm.
190 * See the KeyGenerator section in the <a href=
191 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator">
192 * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
193 * for information about standard algorithm names.
194 *
195 * @return the new <code>KeyGenerator</code> object.
196 *
197 * @exception NullPointerException if the specified algorithm is null.
198 *
199 * @exception NoSuchAlgorithmException if no Provider supports a
200 * KeyGeneratorSpi implementation for the
201 * specified algorithm.
202 *
203 * @see java.security.Provider
204 */
205 public static final KeyGenerator getInstance(String algorithm)
206 throws NoSuchAlgorithmException {
207 return new KeyGenerator(algorithm);
208 }
209
210 /**
211 * Returns a <code>KeyGenerator</code> object that generates secret keys
212 * for the specified algorithm.
213 *
214 * <p> A new KeyGenerator object encapsulating the
215 * KeyGeneratorSpi implementation from the specified provider
216 * is returned. The specified provider must be registered
217 * in the security provider list.
218 *
219 * <p> Note that the list of registered providers may be retrieved via
220 * the {@link Security#getProviders() Security.getProviders()} method.
221 *
222 * @param algorithm the standard name of the requested key algorithm.
223 * See the KeyGenerator section in the <a href=
224 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator">
225 * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
226 * for information about standard algorithm names.
227 *
228 * @param provider the name of the provider.
229 *
230 * @return the new <code>KeyGenerator</code> object.
231 *
232 * @exception NullPointerException if the specified algorithm is null.
233 *
234 * @exception NoSuchAlgorithmException if a KeyGeneratorSpi
235 * implementation for the specified algorithm is not
236 * available from the specified provider.
237 *
238 * @exception NoSuchProviderException if the specified provider is not
239 * registered in the security provider list.
240 *
241 * @exception IllegalArgumentException if the <code>provider</code>
242 * is null or empty.
243 *
244 * @see java.security.Provider
245 */
246 public static final KeyGenerator getInstance(String algorithm,
247 String provider) throws NoSuchAlgorithmException,
248 NoSuchProviderException {
249 Instance instance = JceSecurity.getInstance("KeyGenerator",
250 KeyGeneratorSpi.class, algorithm, provider);
251 return new KeyGenerator((KeyGeneratorSpi)instance.impl,
252 instance.provider, algorithm);
253 }
254
255 /**
256 * Returns a <code>KeyGenerator</code> object that generates secret keys
257 * for the specified algorithm.
258 *
259 * <p> A new KeyGenerator object encapsulating the
260 * KeyGeneratorSpi implementation from the specified Provider
261 * object is returned. Note that the specified Provider object
262 * does not have to be registered in the provider list.
263 *
264 * @param algorithm the standard name of the requested key algorithm.
265 * See the KeyGenerator section in the <a href=
266 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator">
267 * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
268 * for information about standard algorithm names.
269 *
270 * @param provider the provider.
271 *
272 * @return the new <code>KeyGenerator</code> object.
273 *
274 * @exception NullPointerException if the specified algorithm is null.
275 *
276 * @exception NoSuchAlgorithmException if a KeyGeneratorSpi
277 * implementation for the specified algorithm is not available
278 * from the specified Provider object.
279 *
280 * @exception IllegalArgumentException if the <code>provider</code>
281 * is null.
282 *
283 * @see java.security.Provider
284 */
285 public static final KeyGenerator getInstance(String algorithm,
286 Provider provider) throws NoSuchAlgorithmException {
287 Instance instance = JceSecurity.getInstance("KeyGenerator",
288 KeyGeneratorSpi.class, algorithm, provider);
289 return new KeyGenerator((KeyGeneratorSpi)instance.impl,
290 instance.provider, algorithm);
291 }
292
293 /**
294 * Returns the provider of this <code>KeyGenerator</code> object.
295 *
296 * @return the provider of this <code>KeyGenerator</code> object
297 */
298 public final Provider getProvider() {
299 synchronized (lock) {
300 disableFailover();
301 return provider;
302 }
303 }
304
305 /**
306 * Update the active spi of this class and return the next
307 * implementation for failover. If no more implemenations are
308 * available, this method returns null. However, the active spi of
309 * this class is never set to null.
310 */
311 private KeyGeneratorSpi nextSpi(KeyGeneratorSpi oldSpi,
312 boolean reinit) {
313 synchronized (lock) {
314 // somebody else did a failover concurrently
315 // try that spi now
316 if ((oldSpi != null) && (oldSpi != spi)) {
317 return spi;
318 }
319 if (serviceIterator == null) {
320 return null;
321 }
322 while (serviceIterator.hasNext()) {
323 Service s = (Service)serviceIterator.next();
324 if (JceSecurity.canUseProvider(s.getProvider()) == false) {
325 continue;
326 }
327 try {
328 Object inst = s.newInstance(null);
329 // ignore non-spis
330 if (inst instanceof KeyGeneratorSpi == false) {
331 continue;
332 }
333 KeyGeneratorSpi spi = (KeyGeneratorSpi)inst;
334 if (reinit) {
335 if (initType == I_SIZE) {
336 spi.engineInit(initKeySize, initRandom);
337 } else if (initType == I_PARAMS) {
338 spi.engineInit(initParams, initRandom);
339 } else if (initType == I_RANDOM) {
340 spi.engineInit(initRandom);
341 } else if (initType != I_NONE) {
342 throw new AssertionError
343 ("KeyGenerator initType: " + initType);
344 }
345 }
346 provider = s.getProvider();
347 this.spi = spi;
348 return spi;
349 } catch (Exception e) {
350 // ignore
351 }
352 }
353 disableFailover();
354 return null;
355 }
356 }
357
358 void disableFailover() {
359 serviceIterator = null;
360 initType = 0;
361 initParams = null;
362 initRandom = null;
363 }
364
365 /**
366 * Initializes this key generator.
367 *
368 * @param random the source of randomness for this generator
369 */
370 public final void init(SecureRandom random) {
371 if (serviceIterator == null) {
372 spi.engineInit(random);
373 return;
374 }
375 RuntimeException failure = null;
376 KeyGeneratorSpi mySpi = spi;
377 do {
378 try {
379 mySpi.engineInit(random);
380 initType = I_RANDOM;
381 initKeySize = 0;
382 initParams = null;
383 initRandom = random;
384 return;
385 } catch (RuntimeException e) {
386 if (failure == null) {
387 failure = e;
388 }
389 mySpi = nextSpi(mySpi, false);
390 }
391 } while (mySpi != null);
392 throw failure;
393 }
394
395 /**
396 * Initializes this key generator with the specified parameter set.
397 *
398 * <p> If this key generator requires any random bytes, it will get them
399 * using the
400 * {@link SecureRandom <code>SecureRandom</code>}
401 * implementation of the highest-priority installed
402 * provider as the source of randomness.
403 * (If none of the installed providers supply an implementation of
404 * SecureRandom, a system-provided source of randomness will be used.)
405 *
406 * @param params the key generation parameters
407 *
408 * @exception InvalidAlgorithmParameterException if the given parameters
409 * are inappropriate for this key generator
410 */
411 public final void init(AlgorithmParameterSpec params)
412 throws InvalidAlgorithmParameterException
413 {
414 init(params, JceSecurity.RANDOM);
415 }
416
417 /**
418 * Initializes this key generator with the specified parameter
419 * set and a user-provided source of randomness.
420 *
421 * @param params the key generation parameters
422 * @param random the source of randomness for this key generator
423 *
424 * @exception InvalidAlgorithmParameterException if <code>params</code> is
425 * inappropriate for this key generator
426 */
427 public final void init(AlgorithmParameterSpec params, SecureRandom random)
428 throws InvalidAlgorithmParameterException
429 {
430 if (serviceIterator == null) {
431 spi.engineInit(params, random);
432 return;
433 }
434 Exception failure = null;
435 KeyGeneratorSpi mySpi = spi;
436 do {
437 try {
438 mySpi.engineInit(params, random);
439 initType = I_PARAMS;
440 initKeySize = 0;
441 initParams = params;
442 initRandom = random;
443 return;
444 } catch (Exception e) {
445 if (failure == null) {
446 failure = e;
447 }
448 mySpi = nextSpi(mySpi, false);
449 }
450 } while (mySpi != null);
451 if (failure instanceof InvalidAlgorithmParameterException) {
452 throw (InvalidAlgorithmParameterException)failure;
453 }
454 if (failure instanceof RuntimeException) {
455 throw (RuntimeException)failure;
456 }
457 throw new InvalidAlgorithmParameterException("init() failed", failure);
458 }
459
460 /**
461 * Initializes this key generator for a certain keysize.
462 *
463 * <p> If this key generator requires any random bytes, it will get them
464 * using the
465 * {@link SecureRandom <code>SecureRandom</code>}
466 * implementation of the highest-priority installed
467 * provider as the source of randomness.
468 * (If none of the installed providers supply an implementation of
469 * SecureRandom, a system-provided source of randomness will be used.)
470 *
471 * @param keysize the keysize. This is an algorithm-specific metric,
472 * specified in number of bits.
473 *
474 * @exception InvalidParameterException if the keysize is wrong or not
475 * supported.
476 */
477 public final void init(int keysize) {
478 init(keysize, JceSecurity.RANDOM);
479 }
480
481 /**
482 * Initializes this key generator for a certain keysize, using a
483 * user-provided source of randomness.
484 *
485 * @param keysize the keysize. This is an algorithm-specific metric,
486 * specified in number of bits.
487 * @param random the source of randomness for this key generator
488 *
489 * @exception InvalidParameterException if the keysize is wrong or not
490 * supported.
491 */
492 public final void init(int keysize, SecureRandom random) {
493 if (serviceIterator == null) {
494 spi.engineInit(keysize, random);
495 return;
496 }
497 RuntimeException failure = null;
498 KeyGeneratorSpi mySpi = spi;
499 do {
500 try {
501 mySpi.engineInit(keysize, random);
502 initType = I_SIZE;
503 initKeySize = keysize;
504 initParams = null;
505 initRandom = random;
506 return;
507 } catch (RuntimeException e) {
508 if (failure == null) {
509 failure = e;
510 }
511 mySpi = nextSpi(mySpi, false);
512 }
513 } while (mySpi != null);
514 throw failure;
515 }
516
517 /**
518 * Generates a secret key.
519 *
520 * @return the new key
521 */
522 public final SecretKey generateKey() {
523 if (serviceIterator == null) {
524 return spi.engineGenerateKey();
525 }
526 RuntimeException failure = null;
527 KeyGeneratorSpi mySpi = spi;
528 do {
529 try {
530 return mySpi.engineGenerateKey();
531 } catch (RuntimeException e) {
532 if (failure == null) {
533 failure = e;
534 }
535 mySpi = nextSpi(mySpi, true);
536 }
537 } while (mySpi != null);
538 throw failure;
539 }
540}