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+
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
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+}