Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/java/security/KeyFactory.java
41152 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 java.security;
27
28
import java.util.*;
29
30
import java.security.Provider.Service;
31
import java.security.spec.KeySpec;
32
import java.security.spec.InvalidKeySpecException;
33
34
import sun.security.util.Debug;
35
import sun.security.jca.*;
36
import sun.security.jca.GetInstance.Instance;
37
38
/**
39
* Key factories are used to convert <I>keys</I> (opaque
40
* cryptographic keys of type {@code Key}) into <I>key specifications</I>
41
* (transparent representations of the underlying key material), and vice
42
* versa.
43
*
44
* <P> Key factories are bi-directional. That is, they allow you to build an
45
* opaque key object from a given key specification (key material), or to
46
* retrieve the underlying key material of a key object in a suitable format.
47
*
48
* <P> Multiple compatible key specifications may exist for the same key.
49
* For example, a DSA public key may be specified using
50
* {@code DSAPublicKeySpec} or
51
* {@code X509EncodedKeySpec}. A key factory can be used to translate
52
* between compatible key specifications.
53
*
54
* <P> The following is an example of how to use a key factory in order to
55
* instantiate a DSA public key from its encoding.
56
* Assume Alice has received a digital signature from Bob.
57
* Bob also sent her his public key (in encoded format) to verify
58
* his signature. Alice then performs the following actions:
59
*
60
* <pre>
61
* X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(bobEncodedPubKey);
62
* KeyFactory keyFactory = KeyFactory.getInstance("DSA");
63
* PublicKey bobPubKey = keyFactory.generatePublic(bobPubKeySpec);
64
* Signature sig = Signature.getInstance("DSA");
65
* sig.initVerify(bobPubKey);
66
* sig.update(data);
67
* sig.verify(signature);
68
* </pre>
69
*
70
* <p> Every implementation of the Java platform is required to support the
71
* following standard {@code KeyFactory} algorithms:
72
* <ul>
73
* <li>{@code DiffieHellman}</li>
74
* <li>{@code DSA}</li>
75
* <li>{@code RSA}</li>
76
* </ul>
77
* These algorithms are described in the <a href=
78
* "{@docRoot}/../specs/security/standard-names.html#keyfactory-algorithms">
79
* KeyFactory section</a> of the
80
* Java Security Standard Algorithm Names Specification.
81
* Consult the release documentation for your implementation to see if any
82
* other algorithms are supported.
83
*
84
* @author Jan Luehe
85
*
86
* @see Key
87
* @see PublicKey
88
* @see PrivateKey
89
* @see java.security.spec.KeySpec
90
* @see java.security.spec.DSAPublicKeySpec
91
* @see java.security.spec.X509EncodedKeySpec
92
*
93
* @since 1.2
94
*/
95
96
public class KeyFactory {
97
98
private static final Debug debug =
99
Debug.getInstance("jca", "KeyFactory");
100
101
// The algorithm associated with this key factory
102
private final String algorithm;
103
104
// The provider
105
private Provider provider;
106
107
// The provider implementation (delegate)
108
private volatile KeyFactorySpi spi;
109
110
// lock for mutex during provider selection
111
private final Object lock = new Object();
112
113
// remaining services to try in provider selection
114
// null once provider is selected
115
private Iterator<Service> serviceIterator;
116
117
/**
118
* Creates a KeyFactory object.
119
*
120
* @param keyFacSpi the delegate
121
* @param provider the provider
122
* @param algorithm the name of the algorithm
123
* to associate with this {@code KeyFactory}
124
*/
125
protected KeyFactory(KeyFactorySpi keyFacSpi, Provider provider,
126
String algorithm) {
127
this.spi = keyFacSpi;
128
this.provider = provider;
129
this.algorithm = algorithm;
130
}
131
132
private KeyFactory(String algorithm) throws NoSuchAlgorithmException {
133
this.algorithm = algorithm;
134
List<Service> list = GetInstance.getServices("KeyFactory", algorithm);
135
serviceIterator = list.iterator();
136
// fetch and instantiate initial spi
137
if (nextSpi(null) == null) {
138
throw new NoSuchAlgorithmException
139
(algorithm + " KeyFactory not available");
140
}
141
}
142
143
/**
144
* Returns a KeyFactory object that converts
145
* public/private keys of the specified algorithm.
146
*
147
* <p> This method traverses the list of registered security Providers,
148
* starting with the most preferred Provider.
149
* A new KeyFactory object encapsulating the
150
* KeyFactorySpi implementation from the first
151
* Provider that supports the specified algorithm is returned.
152
*
153
* <p> Note that the list of registered providers may be retrieved via
154
* the {@link Security#getProviders() Security.getProviders()} method.
155
*
156
* @implNote
157
* The JDK Reference Implementation additionally uses the
158
* {@code jdk.security.provider.preferred}
159
* {@link Security#getProperty(String) Security} property to determine
160
* the preferred provider order for the specified algorithm. This
161
* may be different than the order of providers returned by
162
* {@link Security#getProviders() Security.getProviders()}.
163
*
164
* @param algorithm the name of the requested key algorithm.
165
* See the KeyFactory section in the <a href=
166
* "{@docRoot}/../specs/security/standard-names.html#keyfactory-algorithms">
167
* Java Security Standard Algorithm Names Specification</a>
168
* for information about standard algorithm names.
169
*
170
* @return the new {@code KeyFactory} object
171
*
172
* @throws NoSuchAlgorithmException if no {@code Provider} supports a
173
* {@code KeyFactorySpi} implementation for the
174
* specified algorithm
175
*
176
* @throws NullPointerException if {@code algorithm} is {@code null}
177
*
178
* @see Provider
179
*/
180
public static KeyFactory getInstance(String algorithm)
181
throws NoSuchAlgorithmException {
182
Objects.requireNonNull(algorithm, "null algorithm name");
183
return new KeyFactory(algorithm);
184
}
185
186
/**
187
* Returns a KeyFactory object that converts
188
* public/private keys of the specified algorithm.
189
*
190
* <p> A new KeyFactory object encapsulating the
191
* KeyFactorySpi implementation from the specified provider
192
* is returned. The specified provider must be registered
193
* in the security provider list.
194
*
195
* <p> Note that the list of registered providers may be retrieved via
196
* the {@link Security#getProviders() Security.getProviders()} method.
197
*
198
* @param algorithm the name of the requested key algorithm.
199
* See the KeyFactory section in the <a href=
200
* "{@docRoot}/../specs/security/standard-names.html#keyfactory-algorithms">
201
* Java Security Standard Algorithm Names Specification</a>
202
* for information about standard algorithm names.
203
*
204
* @param provider the name of the provider.
205
*
206
* @return the new {@code KeyFactory} object
207
*
208
* @throws IllegalArgumentException if the provider name is {@code null}
209
* or empty
210
*
211
* @throws NoSuchAlgorithmException if a {@code KeyFactorySpi}
212
* implementation for the specified algorithm is not
213
* available from the specified provider
214
*
215
* @throws NoSuchProviderException if the specified provider is not
216
* registered in the security provider list
217
*
218
* @throws NullPointerException if {@code algorithm} is {@code null}
219
*
220
* @see Provider
221
*/
222
public static KeyFactory getInstance(String algorithm, String provider)
223
throws NoSuchAlgorithmException, NoSuchProviderException {
224
Objects.requireNonNull(algorithm, "null algorithm name");
225
Instance instance = GetInstance.getInstance("KeyFactory",
226
KeyFactorySpi.class, algorithm, provider);
227
return new KeyFactory((KeyFactorySpi)instance.impl,
228
instance.provider, algorithm);
229
}
230
231
/**
232
* Returns a KeyFactory object that converts
233
* public/private keys of the specified algorithm.
234
*
235
* <p> A new KeyFactory object encapsulating the
236
* KeyFactorySpi implementation from the specified Provider
237
* object is returned. Note that the specified Provider object
238
* does not have to be registered in the provider list.
239
*
240
* @param algorithm the name of the requested key algorithm.
241
* See the KeyFactory section in the <a href=
242
* "{@docRoot}/../specs/security/standard-names.html#keyfactory-algorithms">
243
* Java Security Standard Algorithm Names Specification</a>
244
* for information about standard algorithm names.
245
*
246
* @param provider the provider.
247
*
248
* @return the new {@code KeyFactory} object
249
*
250
* @throws IllegalArgumentException if the specified provider is
251
* {@code null}
252
*
253
* @throws NoSuchAlgorithmException if a {@code KeyFactorySpi}
254
* implementation for the specified algorithm is not available
255
* from the specified {@code Provider} object
256
*
257
* @throws NullPointerException if {@code algorithm} is {@code null}
258
*
259
* @see Provider
260
*
261
* @since 1.4
262
*/
263
public static KeyFactory getInstance(String algorithm, Provider provider)
264
throws NoSuchAlgorithmException {
265
Objects.requireNonNull(algorithm, "null algorithm name");
266
Instance instance = GetInstance.getInstance("KeyFactory",
267
KeyFactorySpi.class, algorithm, provider);
268
return new KeyFactory((KeyFactorySpi)instance.impl,
269
instance.provider, algorithm);
270
}
271
272
/**
273
* Returns the provider of this key factory object.
274
*
275
* @return the provider of this key factory object
276
*/
277
public final Provider getProvider() {
278
synchronized (lock) {
279
// disable further failover after this call
280
serviceIterator = null;
281
return provider;
282
}
283
}
284
285
/**
286
* Gets the name of the algorithm
287
* associated with this {@code KeyFactory}.
288
*
289
* @return the name of the algorithm associated with this
290
* {@code KeyFactory}
291
*/
292
public final String getAlgorithm() {
293
return this.algorithm;
294
}
295
296
/**
297
* Update the active KeyFactorySpi of this class and return the next
298
* implementation for failover. If no more implemenations are
299
* available, this method returns null. However, the active spi of
300
* this class is never set to null.
301
*/
302
private KeyFactorySpi nextSpi(KeyFactorySpi oldSpi) {
303
synchronized (lock) {
304
// somebody else did a failover concurrently
305
// try that spi now
306
if ((oldSpi != null) && (oldSpi != spi)) {
307
return spi;
308
}
309
if (serviceIterator == null) {
310
return null;
311
}
312
while (serviceIterator.hasNext()) {
313
Service s = serviceIterator.next();
314
try {
315
Object obj = s.newInstance(null);
316
if (!(obj instanceof KeyFactorySpi spi)) {
317
continue;
318
}
319
provider = s.getProvider();
320
this.spi = spi;
321
return spi;
322
} catch (NoSuchAlgorithmException e) {
323
// ignore
324
}
325
}
326
serviceIterator = null;
327
return null;
328
}
329
}
330
331
/**
332
* Generates a public key object from the provided key specification
333
* (key material).
334
*
335
* @param keySpec the specification (key material) of the public key.
336
*
337
* @return the public key.
338
*
339
* @throws InvalidKeySpecException if the given key specification
340
* is inappropriate for this key factory to produce a public key.
341
*/
342
public final PublicKey generatePublic(KeySpec keySpec)
343
throws InvalidKeySpecException {
344
if (serviceIterator == null) {
345
return spi.engineGeneratePublic(keySpec);
346
}
347
Exception failure = null;
348
KeyFactorySpi mySpi = spi;
349
do {
350
try {
351
return mySpi.engineGeneratePublic(keySpec);
352
} catch (Exception e) {
353
if (failure == null) {
354
failure = e;
355
}
356
mySpi = nextSpi(mySpi);
357
}
358
} while (mySpi != null);
359
if (failure instanceof RuntimeException) {
360
throw (RuntimeException)failure;
361
}
362
if (failure instanceof InvalidKeySpecException) {
363
throw (InvalidKeySpecException)failure;
364
}
365
throw new InvalidKeySpecException
366
("Could not generate public key", failure);
367
}
368
369
/**
370
* Generates a private key object from the provided key specification
371
* (key material).
372
*
373
* @param keySpec the specification (key material) of the private key.
374
*
375
* @return the private key.
376
*
377
* @throws InvalidKeySpecException if the given key specification
378
* is inappropriate for this key factory to produce a private key.
379
*/
380
public final PrivateKey generatePrivate(KeySpec keySpec)
381
throws InvalidKeySpecException {
382
if (serviceIterator == null) {
383
return spi.engineGeneratePrivate(keySpec);
384
}
385
Exception failure = null;
386
KeyFactorySpi mySpi = spi;
387
do {
388
try {
389
return mySpi.engineGeneratePrivate(keySpec);
390
} catch (Exception e) {
391
if (failure == null) {
392
failure = e;
393
}
394
mySpi = nextSpi(mySpi);
395
}
396
} while (mySpi != null);
397
if (failure instanceof RuntimeException) {
398
throw (RuntimeException)failure;
399
}
400
if (failure instanceof InvalidKeySpecException) {
401
throw (InvalidKeySpecException)failure;
402
}
403
throw new InvalidKeySpecException
404
("Could not generate private key", failure);
405
}
406
407
/**
408
* Returns a specification (key material) of the given key object.
409
* {@code keySpec} identifies the specification class in which
410
* the key material should be returned. It could, for example, be
411
* {@code DSAPublicKeySpec.class}, to indicate that the
412
* key material should be returned in an instance of the
413
* {@code DSAPublicKeySpec} class.
414
*
415
* @param <T> the type of the key specification to be returned
416
*
417
* @param key the key.
418
*
419
* @param keySpec the specification class in which
420
* the key material should be returned.
421
*
422
* @return the underlying key specification (key material) in an instance
423
* of the requested specification class.
424
*
425
* @throws InvalidKeySpecException if the requested key specification is
426
* inappropriate for the given key, or the given key cannot be processed
427
* (e.g., the given key has an unrecognized algorithm or format).
428
*/
429
public final <T extends KeySpec> T getKeySpec(Key key, Class<T> keySpec)
430
throws InvalidKeySpecException {
431
if (serviceIterator == null) {
432
return spi.engineGetKeySpec(key, keySpec);
433
}
434
Exception failure = null;
435
KeyFactorySpi mySpi = spi;
436
do {
437
try {
438
return mySpi.engineGetKeySpec(key, keySpec);
439
} catch (Exception e) {
440
if (failure == null) {
441
failure = e;
442
}
443
mySpi = nextSpi(mySpi);
444
}
445
} while (mySpi != null);
446
if (failure instanceof RuntimeException) {
447
throw (RuntimeException)failure;
448
}
449
if (failure instanceof InvalidKeySpecException) {
450
throw (InvalidKeySpecException)failure;
451
}
452
throw new InvalidKeySpecException
453
("Could not get key spec", failure);
454
}
455
456
/**
457
* Translates a key object, whose provider may be unknown or potentially
458
* untrusted, into a corresponding key object of this key factory.
459
*
460
* @param key the key whose provider is unknown or untrusted.
461
*
462
* @return the translated key.
463
*
464
* @throws InvalidKeyException if the given key cannot be processed
465
* by this key factory.
466
*/
467
public final Key translateKey(Key key) throws InvalidKeyException {
468
if (serviceIterator == null) {
469
return spi.engineTranslateKey(key);
470
}
471
Exception failure = null;
472
KeyFactorySpi mySpi = spi;
473
do {
474
try {
475
return mySpi.engineTranslateKey(key);
476
} catch (Exception e) {
477
if (failure == null) {
478
failure = e;
479
}
480
mySpi = nextSpi(mySpi);
481
}
482
} while (mySpi != null);
483
if (failure instanceof RuntimeException) {
484
throw (RuntimeException)failure;
485
}
486
if (failure instanceof InvalidKeyException) {
487
throw (InvalidKeyException)failure;
488
}
489
throw new InvalidKeyException
490
("Could not translate key", failure);
491
}
492
493
}
494
495