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</code>) 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</code> as a transparent representation of DES
57 * keys, and that provider's secret-key factory for Triple DES keys supports
58 * <code>DESedeKeySpec</code> 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</code> algorithms:
63 * <ul>
64 * <li><tt>DES</tt></li>
65 * <li><tt>DESede</tt></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
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</code> 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</code> 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</code> 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</code> 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</code>
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</code> 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</code> 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</code>
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</code> object.
252 *
253 * @return the provider of this <code>SecretKeyFactory</code> 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</code> object.
265 *
266 * <p>This is the same name that was specified in one of the
267 * <code>getInstance</code> calls that created this
268 * <code>SecretKeyFactory</code> object.
269 *
270 * @return the algorithm name of this <code>SecretKeyFactory</code>
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) {
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</code> 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) {
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</code> and <code>keySpec</code> do not match, or
365 * <code>key</code> references a key on a cryptographic hardware device
366 * whereas <code>keySpec</code> 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 }
|
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
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) {
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) {
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 }
|