001    /* AlgorithmParameterGenerator.java --- Algorithm Parameter Generator
002       Copyright (C) 1999, 2003, 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 java.security;
040    
041    import gnu.java.lang.CPStringBuilder;
042    
043    import gnu.java.security.Engine;
044    
045    import java.lang.reflect.InvocationTargetException;
046    import java.security.spec.AlgorithmParameterSpec;
047    
048    /**
049     * <code>AlgorithmParameterGenerator</code> is used to generate algorithm
050     * parameters for specified algorithms.
051     * 
052     * <p>In case the client does not explicitly initialize the
053     * <code>AlgorithmParameterGenerator</code> (via a call to an
054     * <code>init()</code> method), each provider must supply (and document) a
055     * default initialization. For example, the <b>GNU</b> provider uses a default
056     * modulus prime size of <code>1024</code> bits for the generation of <i>DSA</i>
057     * parameters.
058     *
059     * @author Mark Benvenuto
060     * @since 1.2
061     * @see AlgorithmParameters
062     * @see AlgorithmParameterSpec
063     */
064    public class AlgorithmParameterGenerator
065    {
066      /** Service name for algorithm parameter generators. */
067      private static final String ALGORITHM_PARAMETER_GENERATOR =
068        "AlgorithmParameterGenerator";
069    
070      private AlgorithmParameterGeneratorSpi paramGenSpi;
071      private Provider provider;
072      private String algorithm;
073    
074      /**
075       * Constructs a new instance of <code>AlgorithmParameterGenerator</code>.
076       * 
077       * @param paramGenSpi
078       *          the generator to use.
079       * @param provider
080       *          the provider to use.
081       * @param algorithm
082       *          the algorithm to use.
083       */
084      protected AlgorithmParameterGenerator(AlgorithmParameterGeneratorSpi
085                                            paramGenSpi, Provider provider,
086                                            String algorithm)
087      {
088        this.paramGenSpi = paramGenSpi;
089        this.provider = provider;
090        this.algorithm = algorithm;
091      }
092    
093      /** @return the name of the algorithm. */
094      public final String getAlgorithm()
095      {
096        return algorithm;
097      }
098    
099      /**
100       * Returns a new <code>AlgorithmParameterGenerator</code> instance which
101       * generates algorithm parameters for the specified algorithm.
102       * 
103       * @param algorithm the name of algorithm to use.
104       * @return the new instance.
105       * @throws NoSuchAlgorithmException if <code>algorithm</code> is not
106       *           implemented by any provider.
107       * @throws IllegalArgumentException if <code>algorithm</code> is
108       *           <code>null</code> or is an empty string.
109       */
110      public static AlgorithmParameterGenerator getInstance(String algorithm)
111          throws NoSuchAlgorithmException
112      {
113        Provider[] p = Security.getProviders();
114        NoSuchAlgorithmException lastException = null;
115        for (int i = 0; i < p.length; i++)
116          try
117            {
118              return getInstance(algorithm, p[i]);
119            }
120          catch (NoSuchAlgorithmException x)
121            {
122              lastException = x;
123            }
124        if (lastException != null)
125          throw lastException;
126        throw new NoSuchAlgorithmException(algorithm);
127      }
128    
129      /**
130       * Returns a new <code>AlgorithmParameterGenerator</code> instance which
131       * generates algorithm parameters for the specified algorithm.
132       * 
133       * @param algorithm the name of algorithm to use.
134       * @param provider the name of the {@link Provider} to use.
135       * @return the new instance.
136       * @throws NoSuchAlgorithmException if the algorithm is not implemented by the
137       *           named provider.
138       * @throws NoSuchProviderException if the named provider was not found.
139       * @throws IllegalArgumentException if either <code>algorithm</code> or
140       *           <code>provider</code> is <code>null</code> or empty.
141       */
142      public static AlgorithmParameterGenerator getInstance(String algorithm,
143                                                            String provider)
144          throws NoSuchAlgorithmException, NoSuchProviderException
145      {
146        if (provider == null)
147          throw new IllegalArgumentException("provider MUST NOT be null");
148        provider = provider.trim();
149        if (provider.length() == 0)
150          throw new IllegalArgumentException("provider MUST NOT be empty");
151        Provider p = Security.getProvider(provider);
152        if (p == null)
153          throw new NoSuchProviderException(provider);
154        return getInstance(algorithm, p);
155      }
156    
157      /**
158       * Returns a new <code>AlgorithmParameterGenerator</code> instance which
159       * generates algorithm parameters for the specified algorithm.
160       * 
161       * @param algorithm the name of algorithm to use.
162       * @param provider the {@link Provider} to use.
163       * @return the new instance.
164       * @throws NoSuchAlgorithmException if the algorithm is not implemented by
165       *           {@link Provider}.
166       * @throws IllegalArgumentException if either <code>algorithm</code> or
167       *           <code>provider</code> is <code>null</code>, or if
168       *           <code>algorithm</code> is an empty string.
169       * @since 1.4
170       * @see Provider
171       */
172      public static AlgorithmParameterGenerator getInstance(String algorithm,
173                                                            Provider provider)
174          throws NoSuchAlgorithmException
175      {
176        CPStringBuilder sb = new CPStringBuilder()
177            .append("AlgorithmParameterGenerator for algorithm [")
178            .append(algorithm).append("] from provider[")
179            .append(provider).append("] could not be created");
180        Throwable cause;
181        try
182          {
183            Object spi = Engine.getInstance(ALGORITHM_PARAMETER_GENERATOR,
184                                            algorithm,
185                                            provider);
186            return new AlgorithmParameterGenerator((AlgorithmParameterGeneratorSpi) spi,
187                                                   provider,
188                                                   algorithm);
189          }
190        catch (InvocationTargetException x)
191          {
192            cause = x.getCause();
193            if (cause instanceof NoSuchAlgorithmException)
194              throw (NoSuchAlgorithmException) cause;
195            if (cause == null)
196              cause = x;
197          }
198        catch (ClassCastException x)
199          {
200            cause = x;
201          }
202        NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
203        x.initCause(cause);
204        throw x;
205      }
206    
207      /** @return the {@link Provider} of this generator. */
208      public final Provider getProvider()
209      {
210        return provider;
211      }
212    
213      /**
214       * Initializes this instance with the specified size. Since no source of
215       * randomness is supplied, a default one will be used.
216       * 
217       * @param size
218       *          size (in bits) to use.
219       */
220      public final void init(int size)
221      {
222        init(size, new SecureRandom());
223      }
224    
225      /**
226       * Initializes this instance with the specified key-size and source of
227       * randomness.
228       * 
229       * @param size
230       *          the size (in bits) to use.
231       * @param random
232       *          the {@link SecureRandom} to use.
233       */
234      public final void init(int size, SecureRandom random)
235      {
236        paramGenSpi.engineInit(size, random);
237      }
238    
239      /**
240       * Initializes this instance with the specified {@link AlgorithmParameterSpec}.
241       * Since no source of randomness is supplied, a default one will be used.
242       * 
243       * @param genParamSpec
244       *          the {@link AlgorithmParameterSpec} to use.
245       * @throws InvalidAlgorithmParameterException
246       *           if <code>genParamSpec</code> is invalid.
247       */
248      public final void init(AlgorithmParameterSpec genParamSpec)
249          throws InvalidAlgorithmParameterException
250      {
251        init(genParamSpec, new SecureRandom());
252      }
253    
254      /**
255       * Initializes this instance with the specified {@link AlgorithmParameterSpec}
256       * and source of randomness.
257       * 
258       * @param genParamSpec
259       *          the {@link AlgorithmParameterSpec} to use.
260       * @param random
261       *          the {@link SecureRandom} to use.
262       * @throws InvalidAlgorithmParameterException
263       *           if <code>genParamSpec</code> is invalid.
264       */
265      public final void init(AlgorithmParameterSpec genParamSpec,
266                             SecureRandom random)
267        throws InvalidAlgorithmParameterException
268      {
269        paramGenSpi.engineInit(genParamSpec, random);
270      }
271    
272      /** @return a new instance of {@link AlgorithmParameters}. */
273      public final AlgorithmParameters generateParameters()
274      {
275        return paramGenSpi.engineGenerateParameters();
276      }
277    }