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+
26+package javax.crypto;
27+
28+import java.util.*;
29+
30+import java.security.*;
31+import java.security.Provider.Service;
32+import java.security.spec.*;
33+
34+import sun.security.jca.*;
35+import 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+
110+public 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+}