001/* KeyPairGenerator.java --- Key Pair Generator Class
002   Copyright (C) 1999, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package java.security;
040
041import gnu.java.lang.CPStringBuilder;
042
043import gnu.java.security.Engine;
044
045import java.lang.reflect.InvocationTargetException;
046import java.security.spec.AlgorithmParameterSpec;
047
048/**
049 * <code>KeyPairGenerator</code> is a class used to generate key-pairs for a
050 * security algorithm.
051 * 
052 * <p>The <code>KeyPairGenerator</code> is created with the
053 * <code>getInstance()</code> Factory methods. It is used to generate a pair of
054 * public and private keys for a specific algorithm and associate this key-pair
055 * with the algorithm parameters it was initialized with.</p>
056 *
057 * @see KeyPair
058 * @see AlgorithmParameterSpec
059 * @author Mark Benvenuto
060 * @author Casey Marshall
061 */
062public abstract class KeyPairGenerator extends KeyPairGeneratorSpi
063{
064  /** The service name for key pair generators. */
065  private static final String KEY_PAIR_GENERATOR = "KeyPairGenerator";
066
067  Provider provider;
068  private String algorithm;
069
070  /**
071   * Constructs a new instance of <code>KeyPairGenerator</code>.
072   * 
073   * @param algorithm
074   *          the algorithm to use.
075   */
076  protected KeyPairGenerator(String algorithm)
077  {
078    this.algorithm = algorithm;
079    this.provider = null;
080  }
081
082  /**
083   * Returns the name of the algorithm used.
084   * 
085   * @return the name of the algorithm used.
086   */
087  public String getAlgorithm()
088  {
089    return algorithm;
090  }
091
092  /**
093   * Returns a new instance of <code>KeyPairGenerator</code> which generates
094   * key-pairs for the specified algorithm.
095   * 
096   * @param algorithm the name of the algorithm to use.
097   * @return a new instance repesenting the desired algorithm.
098   * @throws NoSuchAlgorithmException if the algorithm is not implemented by any
099   *           provider.
100   * @throws IllegalArgumentException if <code>algorithm</code> is
101   *           <code>null</code> or is an empty string.
102   */
103  public static KeyPairGenerator getInstance(String algorithm)
104      throws NoSuchAlgorithmException
105  {
106    Provider[] p = Security.getProviders();
107    NoSuchAlgorithmException lastException = null;
108    for (int i = 0; i < p.length; i++)
109      try
110        {
111          return getInstance(algorithm, p[i]);
112        }
113      catch (NoSuchAlgorithmException x)
114        {
115          lastException = x;
116        }
117    if (lastException != null)
118      throw lastException;
119    throw new NoSuchAlgorithmException(algorithm);
120  }
121
122  /**
123   * Returns a new instance of <code>KeyPairGenerator</code> which generates
124   * key-pairs for the specified algorithm from a named provider.
125   * 
126   * @param algorithm the name of the algorithm to use.
127   * @param provider the name of a {@link Provider} to use.
128   * @return a new instance repesenting the desired algorithm.
129   * @throws NoSuchAlgorithmException if the algorithm is not implemented by the
130   *           named provider.
131   * @throws NoSuchProviderException if the named provider was not found.
132   * @throws IllegalArgumentException if either <code>algorithm</code> or
133   *           <code>provider</code> is <code>null</code> or empty.
134   */
135  public static KeyPairGenerator getInstance(String algorithm, String provider)
136      throws NoSuchAlgorithmException, NoSuchProviderException
137  {
138    if (provider == null)
139      throw new IllegalArgumentException("provider MUST NOT be null");
140    provider = provider.trim();
141    if (provider.length() == 0)
142      throw new IllegalArgumentException("provider MUST NOT be empty");
143    Provider p = Security.getProvider(provider);
144    if (p == null)
145      throw new NoSuchProviderException(provider);
146    return getInstance(algorithm, p);
147  }
148
149  /**
150   * Returns a new instance of <code>KeyPairGenerator</code> which generates
151   * key-pairs for the specified algorithm from a designated {@link Provider}.
152   * 
153   * @param algorithm
154   *          the name of the algorithm to use.
155   * @param provider
156   *          the {@link Provider} to use.
157   * @return a new insatnce repesenting the desired algorithm.
158   * @throws NoSuchAlgorithmException
159   *           if the algorithm is not implemented by the {@link Provider}.
160   * @throws IllegalArgumentException if either <code>algorithm</code> or
161   *           <code>provider</code> is <code>null</code>, or if
162   *           <code>algorithm</code> is an empty string.
163   * @since 1.4
164   * @see Provider
165   */
166  public static KeyPairGenerator getInstance(String algorithm, 
167                                             Provider provider)
168    throws NoSuchAlgorithmException
169  {
170    CPStringBuilder sb = new CPStringBuilder("KeyPairGenerator for algorithm [")
171        .append(algorithm).append("] from provider[")
172        .append(provider).append("] ");
173    Object o;
174    try
175      {
176        o = Engine.getInstance(KEY_PAIR_GENERATOR, algorithm, provider);
177      }
178    catch (InvocationTargetException x)
179      {
180        Throwable cause = x.getCause();
181        if (cause instanceof NoSuchAlgorithmException)
182          throw (NoSuchAlgorithmException) cause;
183        if (cause == null)
184          cause = x;
185        sb.append("could not be created");
186        NoSuchAlgorithmException y = new NoSuchAlgorithmException(sb.toString());
187        y.initCause(cause);
188        throw y;
189      }
190    KeyPairGenerator result;
191    if (o instanceof KeyPairGenerator)
192      {
193        result = (KeyPairGenerator) o;
194        result.algorithm = algorithm;
195      }
196    else if (o instanceof KeyPairGeneratorSpi)
197      result = new DummyKeyPairGenerator((KeyPairGeneratorSpi) o, algorithm);
198    else
199      {
200        sb.append("is of an unexpected Type: ").append(o.getClass().getName());
201        throw new NoSuchAlgorithmException(sb.toString());
202      }
203    result.provider = provider;
204    return result;
205  }
206
207  /**
208   * Returns the {@link Provider} of this instance.
209   * 
210   * @return the {@link Provider} of this instance.
211   */
212  public final Provider getProvider()
213  {
214    return provider;
215  }
216
217  /**
218   * Initializes this instance for the specified key size. Since no source of
219   * randomness is specified, a default one will be used.
220   * 
221   * @param keysize
222   *          the size of keys to use.
223   */
224  public void initialize(int keysize)
225  {
226    initialize(keysize, new SecureRandom());
227  }
228
229  /**
230   * Initializes this instance for the specified key size and
231   * {@link SecureRandom}.
232   * 
233   * @param keysize
234   *          the size of keys to use.
235   * @param random
236   *          the {@link SecureRandom} to use.
237   * @since 1.2
238   */
239  public void initialize(int keysize, SecureRandom random)
240  {
241  }
242
243  /**
244   * Initializes this instance with the specified
245   * {@link AlgorithmParameterSpec}. Since no source of randomness is specified,
246   * a default one will be used.
247   * 
248   * @param params
249   *          the {@link AlgorithmParameterSpec} to use.
250   * @throws InvalidAlgorithmParameterException
251   *           if the designated specifications are invalid.
252   * @since 1.2
253   */
254  public void initialize(AlgorithmParameterSpec params)
255    throws InvalidAlgorithmParameterException
256  {
257    initialize(params, new SecureRandom());
258  }
259
260  /**
261   * Initializes this instance with the specified {@link AlgorithmParameterSpec}
262   * and {@link SecureRandom}.
263   * 
264   * @param params
265   *          the {@link AlgorithmParameterSpec} to use.
266   * @param random
267   *          the {@link SecureRandom} to use.
268   * @throws InvalidAlgorithmParameterException
269   *           if the designated specifications are invalid.
270   * @since 1.2
271   */
272  public void initialize(AlgorithmParameterSpec params, SecureRandom random)
273    throws InvalidAlgorithmParameterException
274  {
275    super.initialize(params, random);
276  }
277
278  /**
279   * Generates a new "DSA" {@link KeyPair} from the "GNU" security provider.
280   * 
281   * <p>This method generates a unique key-pair each time it is called.</p>
282   * 
283   * @return a new unique {@link KeyPair}.
284   * @see #generateKeyPair()
285   * @since 1.2
286   */
287  public final KeyPair genKeyPair()
288  {
289    try
290      {
291        return getInstance("DSA", "GNU").generateKeyPair();
292      }
293    catch (Exception e)
294      {
295        System.err.println("genKeyPair failed: " + e);
296        e.printStackTrace();
297        return null;
298      }
299  }
300
301  /**
302   * Generates a new "DSA" {@link KeyPair} from the "GNU" security provider.
303   * 
304   * <p>This method generates a unique key pair each time it is called.</p>
305   * 
306   * @return a new unique {@link KeyPair}.
307   * @see #genKeyPair()
308   */
309  public KeyPair generateKeyPair()
310  {
311    return genKeyPair();
312  }
313}