001    /* KeyPairGenerator.java --- Key Pair Generator Class
002       Copyright (C) 1999, 2002, 2003, 2004, 2005  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>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     */
062    public 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    }