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/java/security/KeyFactory.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/security/KeyFactory.java+474−0
@@ -0,0 +1,474 @@
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 java.security;
27
28import java.util.*;
29
30import java.security.Provider.Service;
31import java.security.spec.KeySpec;
32import java.security.spec.InvalidKeySpecException;
33
34import sun.security.util.Debug;
35import sun.security.jca.*;
36import 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</code>) 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</code> or
51 * <code>X509EncodedKeySpec</code>. 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</code> algorithms:
72 * <ul>
73 * <li><tt>DiffieHellman</tt></li>
74 * <li><tt>DSA</tt></li>
75 * <li><tt>RSA</tt></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
96public 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 <tt>KeyFactory</tt>
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 <tt>KeyFactory</tt>.
270 *
271 * @return the name of the algorithm associated with this
272 * <tt>KeyFactory</tt>
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</code> identifies the specification class in which
393 * the key material should be returned. It could, for example, be
394 * <code>DSAPublicKeySpec.class</code>, to indicate that the
395 * key material should be returned in an instance of the
396 * <code>DSAPublicKeySpec</code> class.
397 *
398 * @param key the key.
399 *
400 * @param keySpec the specification class in which
401 * the key material should be returned.
402 *
403 * @return the underlying key specification (key material) in an instance
404 * of the requested specification class.
405 *
406 * @exception InvalidKeySpecException if the requested key specification is
407 * inappropriate for the given key, or the given key cannot be processed
408 * (e.g., the given key has an unrecognized algorithm or format).
409 */
410 public final <T extends KeySpec> T getKeySpec(Key key, Class<T> keySpec)
411 throws InvalidKeySpecException {
412 if (serviceIterator == null) {
413 return spi.engineGetKeySpec(key, keySpec);
414 }
415 Exception failure = null;
416 KeyFactorySpi mySpi = spi;
417 do {
418 try {
419 return mySpi.engineGetKeySpec(key, keySpec);
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 RuntimeException) {
428 throw (RuntimeException)failure;
429 }
430 if (failure instanceof InvalidKeySpecException) {
431 throw (InvalidKeySpecException)failure;
432 }
433 throw new InvalidKeySpecException
434 ("Could not get key spec", failure);
435 }
436
437 /**
438 * Translates a key object, whose provider may be unknown or potentially
439 * untrusted, into a corresponding key object of this key factory.
440 *
441 * @param key the key whose provider is unknown or untrusted.
442 *
443 * @return the translated key.
444 *
445 * @exception InvalidKeyException if the given key cannot be processed
446 * by this key factory.
447 */
448 public final Key translateKey(Key key) throws InvalidKeyException {
449 if (serviceIterator == null) {
450 return spi.engineTranslateKey(key);
451 }
452 Exception failure = null;
453 KeyFactorySpi mySpi = spi;
454 do {
455 try {
456 return mySpi.engineTranslateKey(key);
457 } catch (Exception e) {
458 if (failure == null) {
459 failure = e;
460 }
461 mySpi = nextSpi(mySpi);
462 }
463 } while (mySpi != null);
464 if (failure instanceof RuntimeException) {
465 throw (RuntimeException)failure;
466 }
467 if (failure instanceof InvalidKeyException) {
468 throw (InvalidKeyException)failure;
469 }
470 throw new InvalidKeyException
471 ("Could not translate key", failure);
472 }
473
474}