History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/crypto/SecretKeyFactory.java (1 of 18352 files). Show all

Unified · Split

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