Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/javax/crypto/SecretKeyFactory.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 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 represents a factory for secret keys.
39
*
40
* <P> Key factories are used to convert <I>keys</I> (opaque
41
* cryptographic keys of type {@code Key}) into <I>key specifications</I>
42
* (transparent representations of the underlying key material), and vice
43
* versa.
44
* Secret key factories operate only on secret (symmetric) keys.
45
*
46
* <P> Key factories are bi-directional, i.e., they allow to build an opaque
47
* key object from a given key specification (key material), or to retrieve
48
* the underlying key material of a key object in a suitable format.
49
*
50
* <P> Application developers should refer to their provider's documentation
51
* to find out which key specifications are supported by the
52
* {@link #generateSecret(java.security.spec.KeySpec) generateSecret} and
53
* {@link #getKeySpec(javax.crypto.SecretKey, java.lang.Class) getKeySpec}
54
* methods.
55
* For example, the DESede (Triple DES) secret-key factory supplied by the
56
* "SunJCE" provider supports {@code DESedeKeySpec} as a transparent
57
* representation of Triple DES keys.
58
*
59
* <p> Every implementation of the Java platform is required to support the
60
* following standard {@code SecretKeyFactory} algorithms:
61
* <ul>
62
* <li>{@code DESede}</li>
63
* </ul>
64
* These algorithms are described in the <a href=
65
* "{@docRoot}/../specs/security/standard-names.html#secretkeyfactory-algorithms">
66
* SecretKeyFactory section</a> of the
67
* Java Security Standard Algorithm Names Specification.
68
* Consult the release documentation for your implementation to see if any
69
* other algorithms are supported.
70
*
71
* @author Jan Luehe
72
*
73
* @see SecretKey
74
* @see javax.crypto.spec.DESedeKeySpec
75
* @see javax.crypto.spec.PBEKeySpec
76
* @since 1.4
77
*/
78
79
public class SecretKeyFactory {
80
81
// The provider
82
private Provider provider;
83
84
// The algorithm associated with this factory
85
private final String algorithm;
86
87
// The provider implementation (delegate)
88
private volatile SecretKeyFactorySpi spi;
89
90
// lock for mutex during provider selection
91
private final Object lock = new Object();
92
93
// remaining services to try in provider selection
94
// null once provider is selected
95
private Iterator<Service> serviceIterator;
96
97
/**
98
* Creates a SecretKeyFactory object.
99
*
100
* @param keyFacSpi the delegate
101
* @param provider the provider
102
* @param algorithm the secret-key algorithm
103
*/
104
protected SecretKeyFactory(SecretKeyFactorySpi keyFacSpi,
105
Provider provider, String algorithm) {
106
this.spi = keyFacSpi;
107
this.provider = provider;
108
this.algorithm = algorithm;
109
}
110
111
private SecretKeyFactory(String algorithm) throws NoSuchAlgorithmException {
112
this.algorithm = algorithm;
113
List<Service> list =
114
GetInstance.getServices("SecretKeyFactory", algorithm);
115
serviceIterator = list.iterator();
116
// fetch and instantiate initial spi
117
if (nextSpi(null) == null) {
118
throw new NoSuchAlgorithmException
119
(algorithm + " SecretKeyFactory not available");
120
}
121
}
122
123
/**
124
* Returns a {@code SecretKeyFactory} object that converts
125
* secret keys of the specified algorithm.
126
*
127
* <p> This method traverses the list of registered security Providers,
128
* starting with the most preferred Provider.
129
* A new SecretKeyFactory object encapsulating the
130
* SecretKeyFactorySpi implementation from the first
131
* Provider that supports the specified algorithm is returned.
132
*
133
* <p> Note that the list of registered providers may be retrieved via
134
* the {@link Security#getProviders() Security.getProviders()} method.
135
*
136
* @implNote
137
* The JDK Reference Implementation additionally uses the
138
* {@code jdk.security.provider.preferred}
139
* {@link Security#getProperty(String) Security} property to determine
140
* the preferred provider order for the specified algorithm. This
141
* may be different than the order of providers returned by
142
* {@link Security#getProviders() Security.getProviders()}.
143
*
144
* @param algorithm the standard name of the requested secret-key
145
* algorithm.
146
* See the SecretKeyFactory section in the <a href=
147
* "{@docRoot}/../specs/security/standard-names.html#secretkeyfactory-algorithms">
148
* Java Security Standard Algorithm Names Specification</a>
149
* for information about standard algorithm names.
150
*
151
* @return the new {@code SecretKeyFactory} object
152
*
153
* @throws NoSuchAlgorithmException if no {@code Provider} supports a
154
* {@code SecretKeyFactorySpi} implementation for the
155
* specified algorithm
156
*
157
* @throws NullPointerException if {@code algorithm} is {@code null}
158
*
159
* @see java.security.Provider
160
*/
161
public static final SecretKeyFactory getInstance(String algorithm)
162
throws NoSuchAlgorithmException {
163
Objects.requireNonNull(algorithm, "null algorithm name");
164
return new SecretKeyFactory(algorithm);
165
}
166
167
/**
168
* Returns a {@code SecretKeyFactory} object that converts
169
* secret keys of the specified algorithm.
170
*
171
* <p> A new SecretKeyFactory object encapsulating the
172
* SecretKeyFactorySpi implementation from the specified provider
173
* is returned. The specified provider must be registered
174
* in the security provider list.
175
*
176
* <p> Note that the list of registered providers may be retrieved via
177
* the {@link Security#getProviders() Security.getProviders()} method.
178
*
179
* @param algorithm the standard name of the requested secret-key
180
* algorithm.
181
* See the SecretKeyFactory section in the <a href=
182
* "{@docRoot}/../specs/security/standard-names.html#secretkeyfactory-algorithms">
183
* Java Security Standard Algorithm Names Specification</a>
184
* for information about standard algorithm names.
185
*
186
* @param provider the name of the provider.
187
*
188
* @return the new {@code SecretKeyFactory} object
189
*
190
* @throws IllegalArgumentException if the {@code provider}
191
* is {@code null} or empty
192
*
193
* @throws NoSuchAlgorithmException if a {@code SecretKeyFactorySpi}
194
* implementation for the specified algorithm is not
195
* available from the specified provider
196
*
197
* @throws NoSuchProviderException if the specified provider is not
198
* registered in the security provider list
199
*
200
* @throws NullPointerException if {@code algorithm} is {@code null}
201
*
202
* @see java.security.Provider
203
*/
204
public static final SecretKeyFactory getInstance(String algorithm,
205
String provider) throws NoSuchAlgorithmException,
206
NoSuchProviderException {
207
Objects.requireNonNull(algorithm, "null algorithm name");
208
Instance instance = JceSecurity.getInstance("SecretKeyFactory",
209
SecretKeyFactorySpi.class, algorithm, provider);
210
return new SecretKeyFactory((SecretKeyFactorySpi)instance.impl,
211
instance.provider, algorithm);
212
}
213
214
/**
215
* Returns a {@code SecretKeyFactory} object that converts
216
* secret keys of the specified algorithm.
217
*
218
* <p> A new SecretKeyFactory object encapsulating the
219
* SecretKeyFactorySpi implementation from the specified Provider
220
* object is returned. Note that the specified Provider object
221
* does not have to be registered in the provider list.
222
*
223
* @param algorithm the standard name of the requested secret-key
224
* algorithm.
225
* See the SecretKeyFactory section in the <a href=
226
* "{@docRoot}/../specs/security/standard-names.html#secretkeyfactory-algorithms">
227
* Java Security Standard Algorithm Names Specification</a>
228
* for information about standard algorithm names.
229
*
230
* @param provider the provider.
231
*
232
* @return the new {@code SecretKeyFactory} object
233
*
234
* @throws IllegalArgumentException if the {@code provider}
235
* is {@code null}
236
*
237
* @throws NoSuchAlgorithmException if a {@code SecretKeyFactorySpi}
238
* implementation for the specified algorithm is not available
239
* from the specified {@code Provider} object
240
*
241
* @throws NullPointerException if {@code algorithm} is {@code null}
242
*
243
* @see java.security.Provider
244
*/
245
public static final SecretKeyFactory getInstance(String algorithm,
246
Provider provider) throws NoSuchAlgorithmException {
247
Objects.requireNonNull(algorithm, "null algorithm name");
248
Instance instance = JceSecurity.getInstance("SecretKeyFactory",
249
SecretKeyFactorySpi.class, algorithm, provider);
250
return new SecretKeyFactory((SecretKeyFactorySpi)instance.impl,
251
instance.provider, algorithm);
252
}
253
254
/**
255
* Returns the provider of this {@code SecretKeyFactory} object.
256
*
257
* @return the provider of this {@code SecretKeyFactory} 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
* Returns the algorithm name of this {@code SecretKeyFactory} object.
269
*
270
* <p>This is the same name that was specified in one of the
271
* {@code getInstance} calls that created this
272
* {@code SecretKeyFactory} object.
273
*
274
* @return the algorithm name of this {@code SecretKeyFactory}
275
* object.
276
*/
277
public final String getAlgorithm() {
278
return this.algorithm;
279
}
280
281
/**
282
* Update the active spi of this class and return the next
283
* implementation for failover. If no more implemenations are
284
* available, this method returns null. However, the active spi of
285
* this class is never set to null.
286
*/
287
private SecretKeyFactorySpi nextSpi(SecretKeyFactorySpi oldSpi) {
288
synchronized (lock) {
289
// somebody else did a failover concurrently
290
// try that spi now
291
if ((oldSpi != null) && (oldSpi != spi)) {
292
return spi;
293
}
294
if (serviceIterator == null) {
295
return null;
296
}
297
while (serviceIterator.hasNext()) {
298
Service s = serviceIterator.next();
299
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
300
continue;
301
}
302
try {
303
Object obj = s.newInstance(null);
304
if (obj instanceof SecretKeyFactorySpi == false) {
305
continue;
306
}
307
SecretKeyFactorySpi spi = (SecretKeyFactorySpi)obj;
308
provider = s.getProvider();
309
this.spi = spi;
310
return spi;
311
} catch (NoSuchAlgorithmException e) {
312
// ignore
313
}
314
}
315
serviceIterator = null;
316
return null;
317
}
318
}
319
320
/**
321
* Generates a {@code SecretKey} object from the provided key
322
* specification (key material).
323
*
324
* @param keySpec the specification (key material) of the secret key
325
*
326
* @return the secret key
327
*
328
* @exception InvalidKeySpecException if the given key specification
329
* is inappropriate for this secret-key factory to produce a secret key.
330
*/
331
public final SecretKey generateSecret(KeySpec keySpec)
332
throws InvalidKeySpecException {
333
if (serviceIterator == null) {
334
return spi.engineGenerateSecret(keySpec);
335
}
336
Exception failure = null;
337
SecretKeyFactorySpi mySpi = spi;
338
do {
339
try {
340
return mySpi.engineGenerateSecret(keySpec);
341
} catch (Exception e) {
342
if (failure == null) {
343
failure = e;
344
}
345
mySpi = nextSpi(mySpi);
346
}
347
} while (mySpi != null);
348
if (failure instanceof InvalidKeySpecException) {
349
throw (InvalidKeySpecException)failure;
350
}
351
throw new InvalidKeySpecException
352
("Could not generate secret key", failure);
353
}
354
355
/**
356
* Returns a specification (key material) of the given key object
357
* in the requested format.
358
*
359
* @param key the key
360
* @param keySpec the requested format in which the key material shall be
361
* returned
362
*
363
* @return the underlying key specification (key material) in the
364
* requested format
365
*
366
* @exception InvalidKeySpecException if the requested key specification is
367
* inappropriate for the given key (e.g., the algorithms associated with
368
* {@code key} and {@code keySpec} do not match, or
369
* {@code key} references a key on a cryptographic hardware device
370
* whereas {@code keySpec} is the specification of a software-based
371
* key), or the given key cannot be dealt with
372
* (e.g., the given key has an algorithm or format not supported by this
373
* secret-key factory).
374
*/
375
public final KeySpec getKeySpec(SecretKey key, Class<?> keySpec)
376
throws InvalidKeySpecException {
377
if (serviceIterator == null) {
378
return spi.engineGetKeySpec(key, keySpec);
379
}
380
Exception failure = null;
381
SecretKeyFactorySpi mySpi = spi;
382
do {
383
try {
384
return mySpi.engineGetKeySpec(key, keySpec);
385
} catch (Exception e) {
386
if (failure == null) {
387
failure = e;
388
}
389
mySpi = nextSpi(mySpi);
390
}
391
} while (mySpi != null);
392
if (failure instanceof InvalidKeySpecException) {
393
throw (InvalidKeySpecException)failure;
394
}
395
throw new InvalidKeySpecException
396
("Could not get key spec", failure);
397
}
398
399
/**
400
* Translates a key object, whose provider may be unknown or potentially
401
* untrusted, into a corresponding key object of this secret-key factory.
402
*
403
* @param key the key whose provider is unknown or untrusted
404
*
405
* @return the translated key
406
*
407
* @exception InvalidKeyException if the given key cannot be processed
408
* by this secret-key factory.
409
*/
410
public final SecretKey translateKey(SecretKey key)
411
throws InvalidKeyException {
412
if (serviceIterator == null) {
413
return spi.engineTranslateKey(key);
414
}
415
Exception failure = null;
416
SecretKeyFactorySpi mySpi = spi;
417
do {
418
try {
419
return mySpi.engineTranslateKey(key);
420
} catch (Exception e) {
421
if (failure == null) {
422
failure = e;
423
}
424
mySpi = nextSpi(mySpi);
425
}
426
} while (mySpi != null);
427
if (failure instanceof InvalidKeyException) {
428
throw (InvalidKeyException)failure;
429
}
430
throw new InvalidKeyException
431
("Could not translate key", failure);
432
}
433
}
434
435