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+
26+package java.security;
27+
28+import java.util.*;
29+
30+import java.security.Provider.Service;
31+import java.security.spec.KeySpec;
32+import java.security.spec.InvalidKeySpecException;
33+
34+import sun.security.util.Debug;
35+import sun.security.jca.*;
36+import 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+
96+public 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+}