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/java/security/KeyFactory.java
38829 views
1
/*
2
* Copyright (c) 1997, 2013, 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}/../technotes/guides/security/StandardNames.html#KeyFactory">
79
* KeyFactory section</a> of the
80
* Java Cryptography Architecture Standard Algorithm Name Documentation.
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
* @param algorithm the name of the requested key algorithm.
157
* See the KeyFactory section in the <a href=
158
* "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory">
159
* Java Cryptography Architecture Standard Algorithm Name Documentation</a>
160
* for information about standard algorithm names.
161
*
162
* @return the new KeyFactory object.
163
*
164
* @exception NoSuchAlgorithmException if no Provider supports a
165
* KeyFactorySpi implementation for the
166
* specified algorithm.
167
*
168
* @see Provider
169
*/
170
public static KeyFactory getInstance(String algorithm)
171
throws NoSuchAlgorithmException {
172
return new KeyFactory(algorithm);
173
}
174
175
/**
176
* Returns a KeyFactory object that converts
177
* public/private keys of the specified algorithm.
178
*
179
* <p> A new KeyFactory object encapsulating the
180
* KeyFactorySpi implementation from the specified provider
181
* is returned. The specified provider must be registered
182
* in the security provider list.
183
*
184
* <p> Note that the list of registered providers may be retrieved via
185
* the {@link Security#getProviders() Security.getProviders()} method.
186
*
187
* @param algorithm the name of the requested key algorithm.
188
* See the KeyFactory section in the <a href=
189
* "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory">
190
* Java Cryptography Architecture Standard Algorithm Name Documentation</a>
191
* for information about standard algorithm names.
192
*
193
* @param provider the name of the provider.
194
*
195
* @return the new KeyFactory object.
196
*
197
* @exception NoSuchAlgorithmException if a KeyFactorySpi
198
* implementation for the specified algorithm is not
199
* available from the specified provider.
200
*
201
* @exception NoSuchProviderException if the specified provider is not
202
* registered in the security provider list.
203
*
204
* @exception IllegalArgumentException if the provider name is null
205
* or empty.
206
*
207
* @see Provider
208
*/
209
public static KeyFactory getInstance(String algorithm, String provider)
210
throws NoSuchAlgorithmException, NoSuchProviderException {
211
Instance instance = GetInstance.getInstance("KeyFactory",
212
KeyFactorySpi.class, algorithm, provider);
213
return new KeyFactory((KeyFactorySpi)instance.impl,
214
instance.provider, algorithm);
215
}
216
217
/**
218
* Returns a KeyFactory object that converts
219
* public/private keys of the specified algorithm.
220
*
221
* <p> A new KeyFactory object encapsulating the
222
* KeyFactorySpi implementation from the specified Provider
223
* object is returned. Note that the specified Provider object
224
* does not have to be registered in the provider list.
225
*
226
* @param algorithm the name of the requested key algorithm.
227
* See the KeyFactory section in the <a href=
228
* "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory">
229
* Java Cryptography Architecture Standard Algorithm Name Documentation</a>
230
* for information about standard algorithm names.
231
*
232
* @param provider the provider.
233
*
234
* @return the new KeyFactory object.
235
*
236
* @exception NoSuchAlgorithmException if a KeyFactorySpi
237
* implementation for the specified algorithm is not available
238
* from the specified Provider object.
239
*
240
* @exception IllegalArgumentException if the specified provider is null.
241
*
242
* @see Provider
243
*
244
* @since 1.4
245
*/
246
public static KeyFactory getInstance(String algorithm, Provider provider)
247
throws NoSuchAlgorithmException {
248
Instance instance = GetInstance.getInstance("KeyFactory",
249
KeyFactorySpi.class, algorithm, provider);
250
return new KeyFactory((KeyFactorySpi)instance.impl,
251
instance.provider, algorithm);
252
}
253
254
/**
255
* Returns the provider of this key factory object.
256
*
257
* @return the provider of this key factory object
258
*/
259
public final Provider getProvider() {
260
synchronized (lock) {
261
// disable further failover after this call
262
serviceIterator = null;
263
return provider;
264
}
265
}
266
267
/**
268
* Gets the name of the algorithm
269
* associated with this {@code KeyFactory}.
270
*
271
* @return the name of the algorithm associated with this
272
* {@code KeyFactory}
273
*/
274
public final String getAlgorithm() {
275
return this.algorithm;
276
}
277
278
/**
279
* Update the active KeyFactorySpi of this class and return the next
280
* implementation for failover. If no more implemenations are
281
* available, this method returns null. However, the active spi of
282
* this class is never set to null.
283
*/
284
private KeyFactorySpi nextSpi(KeyFactorySpi oldSpi) {
285
synchronized (lock) {
286
// somebody else did a failover concurrently
287
// try that spi now
288
if ((oldSpi != null) && (oldSpi != spi)) {
289
return spi;
290
}
291
if (serviceIterator == null) {
292
return null;
293
}
294
while (serviceIterator.hasNext()) {
295
Service s = serviceIterator.next();
296
try {
297
Object obj = s.newInstance(null);
298
if (obj instanceof KeyFactorySpi == false) {
299
continue;
300
}
301
KeyFactorySpi spi = (KeyFactorySpi)obj;
302
provider = s.getProvider();
303
this.spi = spi;
304
return spi;
305
} catch (NoSuchAlgorithmException e) {
306
// ignore
307
}
308
}
309
serviceIterator = null;
310
return null;
311
}
312
}
313
314
/**
315
* Generates a public key object from the provided key specification
316
* (key material).
317
*
318
* @param keySpec the specification (key material) of the public key.
319
*
320
* @return the public key.
321
*
322
* @exception InvalidKeySpecException if the given key specification
323
* is inappropriate for this key factory to produce a public key.
324
*/
325
public final PublicKey generatePublic(KeySpec keySpec)
326
throws InvalidKeySpecException {
327
if (serviceIterator == null) {
328
return spi.engineGeneratePublic(keySpec);
329
}
330
Exception failure = null;
331
KeyFactorySpi mySpi = spi;
332
do {
333
try {
334
return mySpi.engineGeneratePublic(keySpec);
335
} catch (Exception e) {
336
if (failure == null) {
337
failure = e;
338
}
339
mySpi = nextSpi(mySpi);
340
}
341
} while (mySpi != null);
342
if (failure instanceof RuntimeException) {
343
throw (RuntimeException)failure;
344
}
345
if (failure instanceof InvalidKeySpecException) {
346
throw (InvalidKeySpecException)failure;
347
}
348
throw new InvalidKeySpecException
349
("Could not generate public key", failure);
350
}
351
352
/**
353
* Generates a private key object from the provided key specification
354
* (key material).
355
*
356
* @param keySpec the specification (key material) of the private key.
357
*
358
* @return the private key.
359
*
360
* @exception InvalidKeySpecException if the given key specification
361
* is inappropriate for this key factory to produce a private key.
362
*/
363
public final PrivateKey generatePrivate(KeySpec keySpec)
364
throws InvalidKeySpecException {
365
if (serviceIterator == null) {
366
return spi.engineGeneratePrivate(keySpec);
367
}
368
Exception failure = null;
369
KeyFactorySpi mySpi = spi;
370
do {
371
try {
372
return mySpi.engineGeneratePrivate(keySpec);
373
} catch (Exception e) {
374
if (failure == null) {
375
failure = e;
376
}
377
mySpi = nextSpi(mySpi);
378
}
379
} while (mySpi != null);
380
if (failure instanceof RuntimeException) {
381
throw (RuntimeException)failure;
382
}
383
if (failure instanceof InvalidKeySpecException) {
384
throw (InvalidKeySpecException)failure;
385
}
386
throw new InvalidKeySpecException
387
("Could not generate private key", failure);
388
}
389
390
/**
391
* Returns a specification (key material) of the given key object.
392
* {@code keySpec} identifies the specification class in which
393
* the key material should be returned. It could, for example, be
394
* {@code DSAPublicKeySpec.class}, to indicate that the
395
* key material should be returned in an instance of the
396
* {@code DSAPublicKeySpec} class.
397
*
398
* @param <T> the type of the key specification to be returned
399
*
400
* @param key the key.
401
*
402
* @param keySpec the specification class in which
403
* the key material should be returned.
404
*
405
* @return the underlying key specification (key material) in an instance
406
* of the requested specification class.
407
*
408
* @exception InvalidKeySpecException if the requested key specification is
409
* inappropriate for the given key, or the given key cannot be processed
410
* (e.g., the given key has an unrecognized algorithm or format).
411
*/
412
public final <T extends KeySpec> T getKeySpec(Key key, Class<T> keySpec)
413
throws InvalidKeySpecException {
414
if (serviceIterator == null) {
415
return spi.engineGetKeySpec(key, keySpec);
416
}
417
Exception failure = null;
418
KeyFactorySpi mySpi = spi;
419
do {
420
try {
421
return mySpi.engineGetKeySpec(key, keySpec);
422
} catch (Exception e) {
423
if (failure == null) {
424
failure = e;
425
}
426
mySpi = nextSpi(mySpi);
427
}
428
} while (mySpi != null);
429
if (failure instanceof RuntimeException) {
430
throw (RuntimeException)failure;
431
}
432
if (failure instanceof InvalidKeySpecException) {
433
throw (InvalidKeySpecException)failure;
434
}
435
throw new InvalidKeySpecException
436
("Could not get key spec", failure);
437
}
438
439
/**
440
* Translates a key object, whose provider may be unknown or potentially
441
* untrusted, into a corresponding key object of this key factory.
442
*
443
* @param key the key whose provider is unknown or untrusted.
444
*
445
* @return the translated key.
446
*
447
* @exception InvalidKeyException if the given key cannot be processed
448
* by this key factory.
449
*/
450
public final Key translateKey(Key key) throws InvalidKeyException {
451
if (serviceIterator == null) {
452
return spi.engineTranslateKey(key);
453
}
454
Exception failure = null;
455
KeyFactorySpi mySpi = spi;
456
do {
457
try {
458
return mySpi.engineTranslateKey(key);
459
} catch (Exception e) {
460
if (failure == null) {
461
failure = e;
462
}
463
mySpi = nextSpi(mySpi);
464
}
465
} while (mySpi != null);
466
if (failure instanceof RuntimeException) {
467
throw (RuntimeException)failure;
468
}
469
if (failure instanceof InvalidKeyException) {
470
throw (InvalidKeyException)failure;
471
}
472
throw new InvalidKeyException
473
("Could not translate key", failure);
474
}
475
476
}
477
478