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