Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/javax/crypto/KeyGenerator.java
41152 views
1
/*
2
* Copyright (c) 1997, 2021, 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
* See the Keysize Restriction sections of the
87
* {@extLink security_guide_jdk_providers JDK Providers}
88
* document for information on the KeyGenerator defaults used by
89
* JDK providers.
90
* However, note that defaults may vary across different providers.
91
* Additionally, the default value for a provider may change in a future
92
* version. Therefore, it is recommended to explicitly initialize the
93
* KeyGenerator instead of relying on provider-specific defaults.
94
*
95
* <p> Every implementation of the Java platform is required to support the
96
* following standard {@code KeyGenerator} algorithms with the keysizes in
97
* parentheses:
98
* <ul>
99
* <li>{@code AES} (128)</li>
100
* <li>{@code DESede} (168)</li>
101
* <li>{@code HmacSHA1}</li>
102
* <li>{@code HmacSHA256}</li>
103
* </ul>
104
* These algorithms are described in the <a href=
105
* "{@docRoot}/../specs/security/standard-names.html#keygenerator-algorithms">
106
* KeyGenerator section</a> of the
107
* Java Security Standard Algorithm Names Specification.
108
* Consult the release documentation for your implementation to see if any
109
* other algorithms are supported.
110
*
111
* @author Jan Luehe
112
*
113
* @see SecretKey
114
* @since 1.4
115
*/
116
117
public class KeyGenerator {
118
119
private static final Debug pdebug =
120
Debug.getInstance("provider", "Provider");
121
private static final boolean skipDebug =
122
Debug.isOn("engine=") && !Debug.isOn("keygenerator");
123
124
// see java.security.KeyPairGenerator for failover notes
125
126
private static final int I_NONE = 1;
127
private static final int I_RANDOM = 2;
128
private static final int I_PARAMS = 3;
129
private static final int I_SIZE = 4;
130
131
// The provider
132
private Provider provider;
133
134
// The provider implementation (delegate)
135
private volatile KeyGeneratorSpi spi;
136
137
// The algorithm
138
private final String algorithm;
139
140
private final Object lock = new Object();
141
142
private Iterator<Service> serviceIterator;
143
144
private int initType;
145
private int initKeySize;
146
private AlgorithmParameterSpec initParams;
147
private SecureRandom initRandom;
148
149
/**
150
* Creates a KeyGenerator object.
151
*
152
* @param keyGenSpi the delegate
153
* @param provider the provider
154
* @param algorithm the algorithm
155
*/
156
protected KeyGenerator(KeyGeneratorSpi keyGenSpi, Provider provider,
157
String algorithm) {
158
this.spi = keyGenSpi;
159
this.provider = provider;
160
this.algorithm = algorithm;
161
162
if (!skipDebug && pdebug != null) {
163
pdebug.println("KeyGenerator." + algorithm + " algorithm from: " +
164
getProviderName());
165
}
166
}
167
168
private KeyGenerator(String algorithm) throws NoSuchAlgorithmException {
169
this.algorithm = algorithm;
170
List<Service> list =
171
GetInstance.getServices("KeyGenerator", algorithm);
172
serviceIterator = list.iterator();
173
initType = I_NONE;
174
// fetch and instantiate initial spi
175
if (nextSpi(null, false) == null) {
176
throw new NoSuchAlgorithmException
177
(algorithm + " KeyGenerator not available");
178
}
179
180
if (!skipDebug && pdebug != null) {
181
pdebug.println("KeyGenerator." + algorithm + " algorithm from: " +
182
getProviderName());
183
}
184
}
185
186
private String getProviderName() {
187
return (provider == null) ? "(no provider)" : provider.getName();
188
}
189
190
/**
191
* Returns the algorithm name of this {@code KeyGenerator} object.
192
*
193
* <p>This is the same name that was specified in one of the
194
* {@code getInstance} calls that created this
195
* {@code KeyGenerator} object.
196
*
197
* @return the algorithm name of this {@code KeyGenerator} object.
198
*/
199
public final String getAlgorithm() {
200
return this.algorithm;
201
}
202
203
/**
204
* Returns a {@code KeyGenerator} object that generates secret keys
205
* for the specified algorithm.
206
*
207
* <p> This method traverses the list of registered security Providers,
208
* starting with the most preferred Provider.
209
* A new KeyGenerator object encapsulating the
210
* KeyGeneratorSpi implementation from the first
211
* Provider that supports the specified algorithm is returned.
212
*
213
* <p> Note that the list of registered providers may be retrieved via
214
* the {@link Security#getProviders() Security.getProviders()} method.
215
*
216
* @implNote
217
* The JDK Reference Implementation additionally uses the
218
* {@code jdk.security.provider.preferred}
219
* {@link Security#getProperty(String) Security} property to determine
220
* the preferred provider order for the specified algorithm. This
221
* may be different than the order of providers returned by
222
* {@link Security#getProviders() Security.getProviders()}.
223
*
224
* @param algorithm the standard name of the requested key algorithm.
225
* See the KeyGenerator section in the <a href=
226
* "{@docRoot}/../specs/security/standard-names.html#keygenerator-algorithms">
227
* Java Security Standard Algorithm Names Specification</a>
228
* for information about standard algorithm names.
229
*
230
* @return the new {@code KeyGenerator} object
231
*
232
* @throws NoSuchAlgorithmException if no {@code Provider} supports a
233
* {@code KeyGeneratorSpi} implementation for the
234
* specified algorithm
235
*
236
* @throws NullPointerException if {@code algorithm} is {@code null}
237
*
238
* @see java.security.Provider
239
*/
240
public static final KeyGenerator getInstance(String algorithm)
241
throws NoSuchAlgorithmException {
242
Objects.requireNonNull(algorithm, "null algorithm name");
243
return new KeyGenerator(algorithm);
244
}
245
246
/**
247
* Returns a {@code KeyGenerator} object that generates secret keys
248
* for the specified algorithm.
249
*
250
* <p> A new KeyGenerator object encapsulating the
251
* KeyGeneratorSpi implementation from the specified provider
252
* is returned. The specified provider must be registered
253
* in the security provider list.
254
*
255
* <p> Note that the list of registered providers may be retrieved via
256
* the {@link Security#getProviders() Security.getProviders()} method.
257
*
258
* @param algorithm the standard name of the requested key algorithm.
259
* See the KeyGenerator section in the <a href=
260
* "{@docRoot}/../specs/security/standard-names.html#keygenerator-algorithms">
261
* Java Security Standard Algorithm Names Specification</a>
262
* for information about standard algorithm names.
263
*
264
* @param provider the name of the provider.
265
*
266
* @return the new {@code KeyGenerator} object
267
*
268
* @throws IllegalArgumentException if the {@code provider}
269
* is {@code null} or empty
270
*
271
* @throws NoSuchAlgorithmException if a {@code KeyGeneratorSpi}
272
* implementation for the specified algorithm is not
273
* available from the specified provider
274
*
275
* @throws NoSuchProviderException if the specified provider is not
276
* registered in the security provider list
277
*
278
* @throws NullPointerException if {@code algorithm} is {@code null}
279
*
280
* @see java.security.Provider
281
*/
282
public static final KeyGenerator getInstance(String algorithm,
283
String provider) throws NoSuchAlgorithmException,
284
NoSuchProviderException {
285
Objects.requireNonNull(algorithm, "null algorithm name");
286
Instance instance = JceSecurity.getInstance("KeyGenerator",
287
KeyGeneratorSpi.class, algorithm, provider);
288
return new KeyGenerator((KeyGeneratorSpi)instance.impl,
289
instance.provider, algorithm);
290
}
291
292
/**
293
* Returns a {@code KeyGenerator} object that generates secret keys
294
* for the specified algorithm.
295
*
296
* <p> A new KeyGenerator object encapsulating the
297
* KeyGeneratorSpi implementation from the specified Provider
298
* object is returned. Note that the specified Provider object
299
* does not have to be registered in the provider list.
300
*
301
* @param algorithm the standard name of the requested key algorithm.
302
* See the KeyGenerator section in the <a href=
303
* "{@docRoot}/../specs/security/standard-names.html#keygenerator-algorithms">
304
* Java Security Standard Algorithm Names Specification</a>
305
* for information about standard algorithm names.
306
*
307
* @param provider the provider.
308
*
309
* @return the new {@code KeyGenerator} object
310
*
311
* @throws IllegalArgumentException if the {@code provider}
312
* is {@code null}
313
*
314
* @throws NoSuchAlgorithmException if a {@code KeyGeneratorSpi}
315
* implementation for the specified algorithm is not available
316
* from the specified {@code Provider} object
317
*
318
* @throws NullPointerException if {@code algorithm} is {@code null}
319
*
320
* @see java.security.Provider
321
*/
322
public static final KeyGenerator getInstance(String algorithm,
323
Provider provider) throws NoSuchAlgorithmException {
324
Objects.requireNonNull(algorithm, "null algorithm name");
325
Instance instance = JceSecurity.getInstance("KeyGenerator",
326
KeyGeneratorSpi.class, algorithm, provider);
327
return new KeyGenerator((KeyGeneratorSpi)instance.impl,
328
instance.provider, algorithm);
329
}
330
331
/**
332
* Returns the provider of this {@code KeyGenerator} object.
333
*
334
* @return the provider of this {@code KeyGenerator} object
335
*/
336
public final Provider getProvider() {
337
synchronized (lock) {
338
disableFailover();
339
return provider;
340
}
341
}
342
343
/**
344
* Update the active spi of this class and return the next
345
* implementation for failover. If no more implementations are
346
* available, this method returns null. However, the active spi of
347
* this class is never set to null.
348
*/
349
private KeyGeneratorSpi nextSpi(KeyGeneratorSpi oldSpi,
350
boolean reinit) {
351
synchronized (lock) {
352
// somebody else did a failover concurrently
353
// try that spi now
354
if ((oldSpi != null) && (oldSpi != spi)) {
355
return spi;
356
}
357
if (serviceIterator == null) {
358
return null;
359
}
360
while (serviceIterator.hasNext()) {
361
Service s = serviceIterator.next();
362
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
363
continue;
364
}
365
try {
366
Object inst = s.newInstance(null);
367
// ignore non-spis
368
if (inst instanceof KeyGeneratorSpi == false) {
369
continue;
370
}
371
KeyGeneratorSpi spi = (KeyGeneratorSpi)inst;
372
if (reinit) {
373
if (initType == I_SIZE) {
374
spi.engineInit(initKeySize, initRandom);
375
} else if (initType == I_PARAMS) {
376
spi.engineInit(initParams, initRandom);
377
} else if (initType == I_RANDOM) {
378
spi.engineInit(initRandom);
379
} else if (initType != I_NONE) {
380
throw new AssertionError
381
("KeyGenerator initType: " + initType);
382
}
383
}
384
provider = s.getProvider();
385
this.spi = spi;
386
return spi;
387
} catch (Exception e) {
388
// ignore
389
}
390
}
391
disableFailover();
392
return null;
393
}
394
}
395
396
void disableFailover() {
397
serviceIterator = null;
398
initType = 0;
399
initParams = null;
400
initRandom = null;
401
}
402
403
/**
404
* Initializes this key generator.
405
*
406
* @param random the source of randomness for this generator
407
*/
408
public final void init(SecureRandom random) {
409
if (serviceIterator == null) {
410
spi.engineInit(random);
411
return;
412
}
413
RuntimeException failure = null;
414
KeyGeneratorSpi mySpi = spi;
415
do {
416
try {
417
mySpi.engineInit(random);
418
initType = I_RANDOM;
419
initKeySize = 0;
420
initParams = null;
421
initRandom = random;
422
return;
423
} catch (RuntimeException e) {
424
if (failure == null) {
425
failure = e;
426
}
427
mySpi = nextSpi(mySpi, false);
428
}
429
} while (mySpi != null);
430
throw failure;
431
}
432
433
/**
434
* Initializes this key generator with the specified parameter set.
435
*
436
* <p> If this key generator requires any random bytes, it will get them
437
* using the
438
* {@link java.security.SecureRandom}
439
* implementation of the highest-priority installed
440
* provider as the source of randomness.
441
* (If none of the installed providers supply an implementation of
442
* SecureRandom, a system-provided source of randomness will be used.)
443
*
444
* @param params the key generation parameters
445
*
446
* @exception InvalidAlgorithmParameterException if the given parameters
447
* are inappropriate for this key generator
448
*/
449
public final void init(AlgorithmParameterSpec params)
450
throws InvalidAlgorithmParameterException
451
{
452
init(params, JCAUtil.getDefSecureRandom());
453
}
454
455
/**
456
* Initializes this key generator with the specified parameter
457
* set and a user-provided source of randomness.
458
*
459
* @param params the key generation parameters
460
* @param random the source of randomness for this key generator
461
*
462
* @exception InvalidAlgorithmParameterException if {@code params} is
463
* inappropriate for this key generator
464
*/
465
public final void init(AlgorithmParameterSpec params, SecureRandom random)
466
throws InvalidAlgorithmParameterException
467
{
468
if (serviceIterator == null) {
469
spi.engineInit(params, random);
470
return;
471
}
472
Exception failure = null;
473
KeyGeneratorSpi mySpi = spi;
474
do {
475
try {
476
mySpi.engineInit(params, random);
477
initType = I_PARAMS;
478
initKeySize = 0;
479
initParams = params;
480
initRandom = random;
481
return;
482
} catch (Exception e) {
483
if (failure == null) {
484
failure = e;
485
}
486
mySpi = nextSpi(mySpi, false);
487
}
488
} while (mySpi != null);
489
if (failure instanceof InvalidAlgorithmParameterException) {
490
throw (InvalidAlgorithmParameterException)failure;
491
}
492
if (failure instanceof RuntimeException) {
493
throw (RuntimeException)failure;
494
}
495
throw new InvalidAlgorithmParameterException("init() failed", failure);
496
}
497
498
/**
499
* Initializes this key generator for a certain keysize.
500
*
501
* <p> If this key generator requires any random bytes, it will get them
502
* using the
503
* {@link java.security.SecureRandom}
504
* implementation of the highest-priority installed
505
* provider as the source of randomness.
506
* (If none of the installed providers supply an implementation of
507
* SecureRandom, a system-provided source of randomness will be used.)
508
*
509
* @param keysize the keysize. This is an algorithm-specific metric,
510
* specified in number of bits.
511
*
512
* @exception InvalidParameterException if the keysize is wrong or not
513
* supported.
514
*/
515
public final void init(int keysize) {
516
init(keysize, JCAUtil.getDefSecureRandom());
517
}
518
519
/**
520
* Initializes this key generator for a certain keysize, using a
521
* user-provided source of randomness.
522
*
523
* @param keysize the keysize. This is an algorithm-specific metric,
524
* specified in number of bits.
525
* @param random the source of randomness for this key generator
526
*
527
* @exception InvalidParameterException if the keysize is wrong or not
528
* supported.
529
*/
530
public final void init(int keysize, SecureRandom random) {
531
if (serviceIterator == null) {
532
spi.engineInit(keysize, random);
533
return;
534
}
535
RuntimeException failure = null;
536
KeyGeneratorSpi mySpi = spi;
537
do {
538
try {
539
mySpi.engineInit(keysize, random);
540
initType = I_SIZE;
541
initKeySize = keysize;
542
initParams = null;
543
initRandom = random;
544
return;
545
} catch (RuntimeException e) {
546
if (failure == null) {
547
failure = e;
548
}
549
mySpi = nextSpi(mySpi, false);
550
}
551
} while (mySpi != null);
552
throw failure;
553
}
554
555
/**
556
* Generates a secret key.
557
*
558
* @return the new key
559
*/
560
public final SecretKey generateKey() {
561
if (serviceIterator == null) {
562
return spi.engineGenerateKey();
563
}
564
RuntimeException failure = null;
565
KeyGeneratorSpi mySpi = spi;
566
do {
567
try {
568
return mySpi.engineGenerateKey();
569
} catch (RuntimeException e) {
570
if (failure == null) {
571
failure = e;
572
}
573
mySpi = nextSpi(mySpi, true);
574
}
575
} while (mySpi != null);
576
throw failure;
577
}
578
}
579
580