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