1   /* $RCSfile: RSAKeyFactoryImpl.java,v $
2    * $Revision: 1.3 $
3    * $Date: 2002/11/23 11:09:56 $
4    * $Author: uwe_guenther $
5    * $State: Exp $
6    *
7    * Created on November 9, 2001 1:49 PM
8    *
9    * Copyright (C) 2001  Uwe Guenther  <uwe@cscc.de >
10   *
11   * This file is part of the jhbci JCE-ServiceProvider. The jhbci JCE-
12   * ServiceProvider is a library, written in JavaTM, that should be 
13   * used in HBCI banking applications (clients and may be servers),
14   * to do cryptographic operations.
15   *
16   * The jhbci library is free software; you can redistribute it and/or
17   * modify it under the terms of the GNU Lesser General Public
18   * License as published by the Free Software Foundation; either
19   * version 2.1 of the License, or (at your option) any later version.
20   *
21   * The jhbci library is distributed in the hope that it will be useful,
22   * but WITHOUT ANY WARRANTY; without even the implied warranty of
23   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24   * Lesser General Public License for more details.
25   *
26   * You should have received a copy of the GNU Lesser General Public
27   * License along with this library; if not, write to the Free Software
28   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29   *
30   */
31  
32  package de.cscc.crypto.provider;
33  
34  import java.security.InvalidKeyException;
35  import java.security.Key;
36  import java.security.PrivateKey;
37  import java.security.PublicKey;
38  import java.security.interfaces.RSAPrivateCrtKey;
39  import java.security.interfaces.RSAPrivateKey;
40  import java.security.interfaces.RSAPublicKey;
41  import java.security.spec.InvalidKeySpecException;
42  import java.security.spec.KeySpec;
43  import java.security.spec.RSAPrivateCrtKeySpec;
44  import java.security.spec.RSAPrivateKeySpec;
45  import java.security.spec.RSAPublicKeySpec;
46  
47  /** 
48   * RSAKeyFactoryImpl Class.
49   *
50   * @author  <a href=mailto:uwe@cscc.de >Uwe G&uuml;nther </a>
51   *
52   * @version $Revision: 1.3 $
53   */
54  final class RSAKeyFactoryImpl {
55  
56      /** Creates new RSAKeyFactoryImpl */
57      RSAKeyFactoryImpl() {}
58  
59      /**
60       * Returns a string representation of the object. 
61       *
62       * @return  a string representation of the object.
63       */
64      public String toString() {
65          return "[RSAKeyFactory]";
66      }    
67      
68      /**
69       * Generates a private key object from the provided key
70       * specification (key material).
71       *
72       * <p>The following KeySpecs will produce the following instances of its 
73       * matching keys:
74       * <ul>
75       * <li> RSAPrivateCrtKeySpec produces:
76       * <ul>
77       * <li>a instance of RSAPrivateCrtKey</li>
78       * </ul>
79       * </li>
80       * <li> RSAPrivateKeySpec produces:
81       * <ul>
82       * <li>a instance of RSAPrivateKey</li>
83       * </ul>
84       * </li>
85       * </ul>
86       *
87       * @param keySpec the specification (key material) of the private key.
88       *
89       * @return the private key.
90       *
91       * @throws InvalidKeySpecException if the given key specification
92       * is inappropriate for this key factory to produce a private key.
93       * @throws NullPointerException If <code>keySpec</code> or one of the key 
94       * data in <code>keySpec</code> is <code>null</code>. So you have to 
95       * construct a valid keySpec without <code>null</code> fields.
96       * @see java.math.BigInteger
97       */
98      PrivateKey generatePrivate(KeySpec keySpec) 
99              throws InvalidKeySpecException {
100         //Check params for null.                        
101         if (keySpec == null) {
102             throw new NullPointerException("Parameter keySpec is null.");
103         }                                          
104         if (keySpec instanceof RSAPrivateCrtKeySpec) {
105             //May throws NullPointerException if one of the key data of the 
106             //key specification are null.            
107             return new RSAPrivateCrtKeyImpl((RSAPrivateCrtKeySpec) keySpec);
108         }
109         if (keySpec instanceof RSAPrivateKeySpec) {
110             //May throws NullPointerException if one of the key data of the 
111             //key specification are null.            
112             return new RSAPrivateKeyImpl((RSAPrivateKeySpec) keySpec);
113         }        
114         throw new InvalidKeySpecException("Inappropriate KeySpec.");
115     }
116     
117     /**
118      * Generates a public key object from the provided key
119      * specification (key material).
120      *
121      * <p>The following KeySpecs will produce the following instances of its 
122      * matching keys:
123      * <ul>
124      * <li> RSAPublicKeySpec produces:
125      * <ul>
126      * <li>a instance of RSAPublicKey</li>
127      * </ul>
128      * </li>
129      * </ul>
130      *
131      * @param keySpec the specification (key material) of the public key.
132      *
133      * @return the public key.
134      *
135      * @throws InvalidKeySpecException if the given key specification
136      * is inappropriate for this key factory to produce a public key.
137      * @throws NullPointerException If <code>keySpec</code> or one of the key
138      * data in <code>keySpec</code> is <code>null</code>. So you have to 
139      * construct a valid keySpec without <code>null</code> fields.
140      * @throws IllegalArgumentException if any key material from keySpec is 
141      * negative.
142      */
143     PublicKey generatePublic(KeySpec keySpec) 
144             throws InvalidKeySpecException {
145         //Check params for null.                        
146         if (keySpec == null) {
147             throw new NullPointerException("Parameter keySpec is null.");
148         }                          
149         
150         if (keySpec instanceof RSAPublicKeySpec) {
151             //May throws NullPointerException if one of the key data of the 
152             //key specification are null.              
153             return new RSAPublicKeyImpl((RSAPublicKeySpec) keySpec);
154         }        
155         throw new InvalidKeySpecException("Inappropriate KeySpec.");
156     }
157     
158     /**
159      * Returns a specification (key material) of the given key
160      * object.
161      * <code>keySpec</code> identifies the specification class in which
162      * the key material should be returned. It could, for example, be
163      * <code>RSAPublicKeySpec.class</code>, to indicate that the
164      * key material should be returned in an instance of the
165      * <code>RSAPublicKeySpec</code> class.
166      *
167      * <p>The following conversions are valid for this provider:
168      * <ul>
169      * <li>RSAPrivateCrtKey:
170      * <ul>
171      * <li>to RSAPrivateCrtKeySpec</li>
172      * <li>to RSAPrivateKeySpec</li>
173      * <li>to RSAPublicKeySpec</li>
174      * </ul>
175      * </li>
176      * <li>RSAPrivateKey:
177      * <ul>
178      * <li>to RSAPrivateKeySpec</li>
179      * </ul>
180      * </li>
181      * <li>RSAPublicKey:
182      * <ul>
183      * <li>to RSAPublicKeySpec</li>
184      * </ul>
185      * </li>
186      * </ul>
187      *
188      * @param key the key.
189      *
190      * @param keySpec the specification class in which
191      * the key material should be returned.
192      *
193      * @return the underlying key specification (key material) in an instance
194      * of the requested specification class.
195      *
196      * @throws InvalidKeySpecException if the requested key specification is
197      * inappropriate for the given key, or the given key cannot be dealt with
198      * (e.g., the given key has an unrecognized format).
199      * @throws NullPointerException If one of the params or one of the needed 
200      * key data in the <code>key</code> is <code>null</code>. So you have to 
201      * produce a valid key without <code>null</code> fields with your 
202      * KeyPairGenerator. This should not be a problem with keys from this 
203      * provider, but maybe with keys from other providers.
204      * @throws IllegalArgumentException if any key material in the key
205      * <code>key</code> is negative. This should not be a problem with keys 
206      * from this provider, but maybe with keys from other providers.
207      */
208     KeySpec getKeySpec(Key key, Class keySpec) 
209             throws InvalidKeySpecException {
210         //Check params for null.        
211         if (key == null) {
212             throw new NullPointerException("Parameter key is null.");
213         }                  
214         if (keySpec == null) {
215             throw new NullPointerException("Parameter keySpec is null.");
216         }          
217         
218         /////////////////////////////////////////
219         //
220         // We can convert a RSAPrivateCrtKey into:
221         //
222         // RSAPrivateCrtKey
223         //   '-> RSAPrivateCrtKeySpec
224         //   '-> RSAPrivateKeySpec
225         //   '-> RSAPublicKeySpec
226         //
227         if (key instanceof RSAPrivateCrtKey) {
228             if (keySpec == RSAPrivateCrtKeySpec.class) {
229                 //May throws NullPointerException if one of the key data of a 
230                 //foreign provider key are null.                                
231                 return new RSAPrivateCrtKeyImpl(
232                         (RSAPrivateCrtKey) key).getKeySpec();
233             }            
234             if (keySpec == RSAPrivateKeySpec.class) {
235                 //May throws NullPointerException if one of the key data of a 
236                 //foreign provider key are null.                                
237                 return new RSAPrivateKeyImpl((RSAPrivateKey) key).getKeySpec();                
238             }
239             if (keySpec == RSAPublicKeySpec.class) {
240                 //May throws NullPointerException if one of the key data of a 
241                 //foreign provider key are null.                                
242                 return new RSAPublicKeyImpl((RSAPrivateCrtKey) key).getKeySpec();
243             }
244             //We got a inappropriate KeySpec for a RSAPrivateCrtKey
245             throw new InvalidKeySpecException("Inappropriate KeySpec.");
246         }
247         
248         //////////////////////////////////////
249         //
250         // We can convert a RSAPrivateKey into:
251         //
252         // RSAPrivateKey
253         //   '-> RSAPrivateKeySpec
254         //        
255         if (key instanceof RSAPrivateKey) {
256             if (keySpec == RSAPrivateKeySpec.class) {
257                 //May throws NullPointerException if one of the key data of a 
258                 //foreign provider key are null.                                
259                 return new RSAPrivateKeyImpl((RSAPrivateKey) key).getKeySpec();
260             }        
261             //We got a inappropriate KeySpec for a RSAPrivateKey
262             throw new InvalidKeySpecException("Inappropriate KeySpec.");
263         }
264 
265         /////////////////////////////////////
266         //
267         // We can convert a RSAPublicKey into:
268         //
269         // RSAPublicKey
270         //   '-> RSAPublicKeySpec
271         //                
272         if (key instanceof RSAPublicKey) {
273             if (keySpec == RSAPublicKeySpec.class) {
274                 //May throws NullPointerException if one of the key data of a 
275                 //foreign provider key are null.                
276                 return new RSAPublicKeyImpl((RSAPublicKey) key).getKeySpec();
277             }
278             //We got a inappropriate KeySpec for a RSAPublicKey
279             throw new InvalidKeySpecException("Inappropriate KeySpec.");
280         }
281         
282         //////////////////////////////////////////////////////////////////
283         //
284         // At this point we are wrong!
285         //
286         // The key is'nt a instanceof either:
287         //                                    * RSAPrivateCrtKey,
288         //                                    * RSAPrivateKey
289         //                                    * RSAPublicKey
290         //
291         // So we have to tell the user that the key has an unrecogniced
292         // format for converting with these KeyFactory!
293         //
294         throw new InvalidKeySpecException("Key has unrecognized format.");
295     }
296     
297     /**
298      * Translates a key object, whose provider may be unknown or
299      * potentially untrusted, into a corresponding key object of this key
300      * factory.
301      *
302      * <p>The following translations are valid for this provider:
303      * <ul>
304      * <li>RSAPrivateCrtKey:
305      * <ul>
306      * <li>to RSAPrivateCrtKey</li>
307      * </ul>
308      * </li>
309      * <li>RSAPrivateKey:
310      * <ul>
311      * <li>to RSAPrivateKey</li>
312      * </ul>
313      * </li>
314      * <li>RSAPublicKey:
315      * <ul>
316      * <li>to RSAPublicKey</li>
317      * </ul>
318      * </li>
319      * </ul>
320      *
321      * @param key the key whose provider is unknown or untrusted.
322      *
323      * @return the translated key.
324      *
325      * @throws InvalidKeyException if the given key cannot be processed
326      * by this key factory.
327      * @throws NullPointerException If the <code>key</code> it self or one of 
328      * the key data in the <code>key</code> is <code>null</code>. So you have to
329      * produce a valid key without <code>null</code> fields with your 
330      * KeyPairGenerator. This should not be a problem with this provider, but 
331      * maybe with other providers.
332      * @throws IllegalArgumentException if any key material in the key
333      * <code>key</code> is negative. This should not be a problem with keys 
334      * from this provider, but maybe with keys from other providers.     
335      */
336     Key translateKey(Key key) throws InvalidKeyException {
337         //Check params for null.
338         if (key == null) {
339             throw new NullPointerException("Parameter key is null.");
340         }        
341         
342         ////////////////////////////////////////////////////
343         //
344         // We can translate a foreign RSAPrivateCrtKey into:
345         //
346         // foreign RSAPrivateCrtKey
347         //          '-> into a JHBCI RSAPrivateCrtKey
348         //       
349         if (key instanceof RSAPrivateCrtKey) {
350             //May throws NullPointerException if one of the key data of a 
351             //foreign provider key are null.                        
352             return new RSAPrivateCrtKeyImpl((RSAPrivateCrtKey) key);
353         }
354         
355         
356         ////////////////////////////////////////////////////
357         //
358         // We can translate a foreign RSAPrivateKey into:
359         //
360         // foreign RSAPrivateKey
361         //          '-> into a JHBCI RSAPrivateKey
362         //               
363         if (key instanceof RSAPrivateKey) {
364             //May throws NullPointerException if one of the key data of a 
365             //foreign provider key are null.                        
366             return new RSAPrivateKeyImpl((RSAPrivateKey) key);
367         }        
368         
369         
370         ////////////////////////////////////////////////////
371         //
372         // We can translate a foreign RSAPublicKey into:
373         //
374         // foreign RSAPublicKey
375         //          '-> into a JHBCI RSAPublicKey
376         //                       
377         if (key instanceof RSAPublicKey) {
378             //May throws NullPointerException if one of the key data of a 
379             //foreign provider key are null.            
380             return new RSAPublicKeyImpl((RSAPublicKey) key);
381         }
382         
383         
384         //////////////////////////////////////////////////////////////////
385         //
386         // At this point we are wrong!
387         //
388         // The key is'nt a instanceof either:
389         //                                    * RSAPrivateCrtKey,
390         //                                    * RSAPrivateKey
391         //                                    * RSAPublicKey
392         //
393         // So we have to tell the user that the key has an unrecogniced
394         // format for translateing with these KeyFactory!
395         //
396         throw new InvalidKeyException("Key has unrecognized format.");
397     }
398 }
399