001    /* KeyGenerator.java -- Interface to a symmetric key generator.
002       Copyright (C) 2004  Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package javax.crypto;
040    
041    import gnu.java.security.Engine;
042    
043    import java.lang.reflect.InvocationTargetException;
044    import java.security.InvalidAlgorithmParameterException;
045    import java.security.NoSuchAlgorithmException;
046    import java.security.NoSuchProviderException;
047    import java.security.Provider;
048    import java.security.SecureRandom;
049    import java.security.Security;
050    import java.security.spec.AlgorithmParameterSpec;
051    
052    /**
053     * A generic producer of keys for symmetric cryptography. The keys
054     * returned may be simple wrappers around byte arrays, or, if the
055     * target cipher requires them, more complex objects.
056     *
057     * @author Casey Marshall (csm@gnu.org)
058     * @since 1.4
059     * @see Cipher
060     * @see Mac
061     */
062    public class KeyGenerator
063    {
064    
065      // Constants and fields.
066      // ------------------------------------------------------------------------
067    
068      private static final String SERVICE = "KeyGenerator";
069    
070      /** The underlying generator implementation. */
071      private KeyGeneratorSpi kgSpi;
072    
073      /** The provider of the implementation. */
074      private Provider provider;
075    
076      /** The name of the algorithm. */
077      private String algorithm;
078    
079      // Constructor.
080      // ------------------------------------------------------------------------
081    
082      /**
083       * Create a new key generator.
084       *
085       * @param kgSpi     The underlying generator.
086       * @param provider  The provider of this implementation.
087       * @param algorithm The algorithm's name.
088       */
089      protected KeyGenerator(KeyGeneratorSpi kgSpi, Provider provider,
090                             String algorithm)
091      {
092        this.kgSpi = kgSpi;
093        this.provider = provider;
094        this.algorithm = algorithm;
095      }
096    
097      /**
098       * Create a new key generator, returning the first available implementation.
099       *
100       * @param algorithm The generator algorithm name.
101       * @throws NoSuchAlgorithmException If the specified algorithm does not exist.
102       * @throws IllegalArgumentException if <code>algorithm</code> is
103       *           <code>null</code> or is an empty string.
104       */
105      public static final KeyGenerator getInstance(String algorithm)
106          throws NoSuchAlgorithmException
107      {
108        Provider[] p = Security.getProviders();
109        NoSuchAlgorithmException lastException = null;
110        for (int i = 0; i < p.length; i++)
111          try
112            {
113              return getInstance(algorithm, p[i]);
114            }
115          catch (NoSuchAlgorithmException x)
116            {
117              lastException = x;
118            }
119        if (lastException != null)
120          throw lastException;
121        throw new NoSuchAlgorithmException(algorithm);
122      }
123    
124      /**
125       * Create a new key generator from the named provider.
126       *
127       * @param algorithm The generator algorithm name.
128       * @param provider The name of the provider to use.
129       * @return An appropriate key generator, if found.
130       * @throws NoSuchAlgorithmException If the specified algorithm is not
131       *           implemented by the named provider.
132       * @throws NoSuchProviderException If the named provider does not exist.
133       * @throws IllegalArgumentException if either <code>algorithm</code> or
134       *           <code>provider</code> is <code>null</code>, or if
135       *           <code>algorithm</code> is an empty string.
136       */
137      public static final KeyGenerator getInstance(String algorithm, String provider)
138          throws NoSuchAlgorithmException, NoSuchProviderException
139      {
140        if (provider == null)
141          throw new IllegalArgumentException("provider MUST NOT be null");
142        Provider p = Security.getProvider(provider);
143        if (p == null)
144          throw new NoSuchProviderException(provider);
145        return getInstance(algorithm, p);
146      }
147    
148      /**
149       * Create a new key generator from the supplied provider.
150       *
151       * @param algorithm The generator algorithm name.
152       * @param provider The provider to use.
153       * @return An appropriate key generator, if found.
154       * @throws NoSuchAlgorithmException If the specified algorithm is not
155       *           implemented by the provider.
156       * @throws IllegalArgumentException if either <code>algorithm</code> or
157       *           <code>provider</code> is <code>null</code>, or if
158       *           <code>algorithm</code> is an empty string.
159       */
160      public static final KeyGenerator getInstance(String algorithm,
161                                                   Provider provider)
162          throws NoSuchAlgorithmException
163      {
164        StringBuilder sb = new StringBuilder("KeyGenerator algorithm [")
165            .append(algorithm).append("] from provider[")
166            .append(provider).append("] could not be created");
167        Throwable cause;
168        try
169          {
170            Object spi = Engine.getInstance(SERVICE, algorithm, provider);
171            KeyGenerator instance = new KeyGenerator((KeyGeneratorSpi) spi,
172                                                     provider,
173                                                     algorithm);
174            instance.init(new SecureRandom());
175            return instance;
176          }
177        catch (InvocationTargetException x)
178          {
179            cause = x.getCause();
180            if (cause instanceof NoSuchAlgorithmException)
181              throw (NoSuchAlgorithmException) cause;
182            if (cause == null)
183              cause = x;
184          }
185        catch (ClassCastException x)
186          {
187            cause = x;
188          }
189        NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
190        x.initCause(cause);
191        throw x;
192      }
193    
194      /**
195       * Generate a key.
196       *
197       * @return The new key.
198       */
199      public final SecretKey generateKey()
200      {
201        return kgSpi.engineGenerateKey();
202      }
203    
204      /**
205       * Return the name of this key generator.
206       *
207       * @return The algorithm name.
208       */
209      public final String getAlgorithm()
210      {
211        return algorithm;
212      }
213    
214      /**
215       * Return the provider of the underlying implementation.
216       *
217       * @return The provider.
218       */
219      public final Provider getProvider()
220      {
221        return provider;
222      }
223    
224      /**
225       * Initialize this key generator with a set of parameters; the
226       * highest-priority {@link java.security.SecureRandom} implementation
227       * will be used.
228       *
229       * @param params The algorithm parameters.
230       * @throws java.security.InvalidAlgorithmParameterException If the
231       *         supplied parameters are inapproprate.
232       */
233      public final void init(AlgorithmParameterSpec params)
234        throws InvalidAlgorithmParameterException
235      {
236        init(params, new SecureRandom());
237      }
238    
239      /**
240       * Initialize this key generator with a set of parameters and a source
241       * of randomness.
242       *
243       * @param params The algorithm parameters.
244       * @param random The source of randomness.
245       * @throws java.security.InvalidAlgorithmParameterException If the
246       *         supplied parameters are inapproprate.
247       */
248      public final void init(AlgorithmParameterSpec params, SecureRandom random)
249        throws InvalidAlgorithmParameterException
250      {
251        kgSpi.engineInit(params, random);
252      }
253    
254      /**
255       * Initialize this key generator with a key size (in bits); the
256       * highest-priority {@link java.security.SecureRandom} implementation
257       * will be used.
258       *
259       * @param keySize The target key size, in bits.
260       * @throws java.security.InvalidParameterException If the
261       *         key size is unsupported.
262       */
263      public final void init(int keySize)
264      {
265        init(keySize, new SecureRandom());
266      }
267    
268      /**
269       * Initialize this key generator with a key size (in bits) and a
270       * source of randomness.
271       *
272       * @param keySize The target key size, in bits.
273       * @param random  The source of randomness.
274       * @throws java.security.InvalidAlgorithmParameterException If the
275       *         key size is unsupported.
276       */
277      public final void init(int keySize, SecureRandom random)
278      {
279        kgSpi.engineInit(keySize, random);
280      }
281    
282      /**
283       * Initialize this key generator with a source of randomness. The
284       * implementation-specific default parameters (such as key size) will
285       * be used.
286       *
287       * @param random The source of randomness.
288       */
289      public final void init(SecureRandom random)
290      {
291        kgSpi.engineInit(random);
292      }
293    }