1   /* $RCSfile: RSAPrivateKeyImpl.java,v $
2    * $Revision: 1.7 $
3    * $Date: 2002/11/23 11:09:56 $
4    * $Author: uwe_guenther $
5    * $State: Exp $
6    *
7    * Created on November 6, 2001 10:12 AM
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.io.IOException;
35  import java.io.ObjectInputStream;
36  import java.io.ObjectOutputStream;
37  import java.math.BigInteger;
38  import java.security.interfaces.RSAPrivateKey;
39  import java.security.spec.KeySpec;
40  import java.security.spec.RSAPrivateKeySpec;
41  
42  /** 
43   * RSAPrivateKeyImpl Class.
44   *
45   * @author  <a href=mailto:uwe@cscc.de >Uwe G&uuml;nther </a>
46   *
47   * @version $Revision: 1.7 $
48   */
49  final class RSAPrivateKeyImpl implements RSAPrivateKey {
50  
51      /**
52       * The class fingerprint that is set to indicate 
53       * serialization compatibility with a previous and
54       * future versions of the class.
55       */
56      private static final long serialVersionUID = -6722298866511615523L;
57      
58      /**
59       * RSA modulus. Must be non-null.
60       *
61       * @serial
62       */
63      private transient BigInteger modulus;
64  
65      /**
66       * RSA private exponent. Must be non-null.
67       *
68       * @serial
69       */
70      private transient BigInteger privateExponent;
71  
72      /** 
73       * This package private constructor will be used from the 
74       * RSAKeyPairGeneratorEngine. 
75       *
76       * <p>Creates new RSAPrivateKeyImpl  from two <code>BigInteger</code>
77       * values. There are no checks for specific invariants. A valid 
78       * <code>BigInteger</code> value is also a valid parameter.
79       *
80       * @param modulus The modulus of this private RSA key.
81       * @param privateExponent The private exponent of this private RSA key.
82       * @throws NullPointerException If either <code>modulus</code> or 
83       * <code>privateExponent</code> is <code>null</code>.
84       * @see java.math.BigInteger
85       * @see de.cscc.crypto.provider.RSAKeyPairGeneratorEngine
86       */
87      RSAPrivateKeyImpl(BigInteger modulus, BigInteger privateExponent) {
88          //May throws NullPointerException if one of the key data is null.
89          initialize(modulus, privateExponent);
90      }
91       
92      /** 
93       * This package private constructor will be used from the 
94       * RSAKeyFactoryEngine.
95       *
96       * <p>Creates new RSAPrivateKeyImpl from an instance of a class that 
97       * implements the RSAPrivateKey interface. May be this will be a class
98       * from a foreign provider, so we do all checks, which we have to do with
99       * pur BigIntegers.
100      *
101      * @param key existing key may from a foreign provider.
102      * @throws NullPointerException If <code>key</code> is <code>null</null> or
103      * one of keys 'key data' is <code>null</code>.
104      * @see de.cscc.crypto.provider.RSAKeyFactoryEngine
105      */    
106     RSAPrivateKeyImpl(RSAPrivateKey key) {
107         //Check params for null.
108         if (key == null) {
109             throw new NullPointerException("Parameter key is null.");
110         }
111         //May throws NullPointerException if one of the key data of a foreign
112         //provider key are null.
113         initialize(key.getModulus(), key.getPrivateExponent());
114     }  
115     
116     /** 
117      * This package private constructor will be used from the 
118      * RSAKeyFactoryEngine.
119      *
120      * <p>Creates new RSAPrivateKeyImpl from an instance of a RSAPrivateKeySpec 
121      * class. May be this class contains null references instead BigInterger,
122      * so we do all checks, which we have to do with pur BigIntegers.
123      *
124      * @param keySpec transparent specification that holds the key material.
125      * @throws NullPointerException If <code>keySpec</code> is <code>null</null>
126      * or one of the key specifakations 'key data' is <code>null</code>.
127      * @see de.cscc.crypto.provider.RSAKeyFactoryEngine
128      */    
129     RSAPrivateKeyImpl(RSAPrivateKeySpec keySpec) {
130         //Check params for null.
131         if (keySpec == null) {
132             throw new NullPointerException("Parameter keySpec is null.");
133         }
134         //May throws NullPointerException if one of the key data are null.
135         initialize(keySpec.getModulus(), keySpec.getPrivateExponent());
136     }        
137     
138     
139     /** 
140      * Private helper method, only used from the constructors and 
141      * pseudo-constructors like readObject.
142      *
143      * Initializes a new RSAPrivateKeyImpl  from two <code>BigInteger</code>
144      * values. There are no checks for specific invariants. A valid 
145      * <code>BigInteger</code> value is also a valid parameter.
146      *
147      * @param modulus The modulus of this private RSA key.
148      * @param privateExponent The private exponent of this private RSA key.
149      * @throws NullPointerException If either <code>modulus</code> or 
150      * <code>privateExponent</code> is <code>null</code>.
151      * @throws IllegalArgumentException if any Parameter is negative.
152      * @see java.math.BigInteger
153      */
154     private void initialize(BigInteger modulus, BigInteger privateExponent) {
155         //Check params for null.
156         if (modulus == null) {
157             throw new NullPointerException("Parameter modulus is null.");
158         }
159         if (privateExponent == null) {
160             throw new NullPointerException(
161                     "Parameter privateExponent is null.");
162         }
163         
164         //Check params if the they real BigInteger, and not subclasses.
165         //If a param is a subclasses we construct a new real BigInteger from
166         //the specific param value.
167         if (modulus.getClass() != BigInteger.class) {
168             modulus = new BigInteger(modulus.toByteArray());
169         }
170         if (privateExponent.getClass() !=BigInteger.class) {
171             privateExponent = new BigInteger(privateExponent.toByteArray());
172         }
173         
174         //Check if the params not negative
175         if (modulus.compareTo(BigInteger.ZERO) < 0) {
176             throw new IllegalArgumentException(
177             "Parameter modulus is negative. modulus: " + modulus);
178         }
179         if (privateExponent.compareTo(BigInteger.ZERO) < 0) {
180             throw new IllegalArgumentException(
181             "Parameter privateExponent is negative. privateExponent: " +
182             privateExponent);
183         }                
184         
185         //We do only copy the references to the BigInteger objects,
186         //because BigInteger are immutable and this class too.
187         this.modulus = modulus;
188         this.privateExponent = privateExponent;
189     }    
190     
191     /**
192      * Indicates whether some other object is "equal to" this one.
193      *
194      * @param   obj   the reference object with which to compare.
195      * @return  <code>true</code> if this object is the same as the obj
196      *         argument; <code>false</code> otherwise.
197      * @see     #hashCode()
198      * @see     java.util.Hashtable
199      */
200     public boolean equals(Object obj) {
201         //Only for performance.
202         if (this == obj) {
203             return true;
204         } 
205         
206         //If obj == null then instanceof returns false, see JLS 15.20.2
207         if (!(obj instanceof RSAPrivateKeyImpl)) {
208             return false;
209         }
210         
211         RSAPrivateKeyImpl other = (RSAPrivateKeyImpl) obj;
212         return this.modulus.equals(other.modulus) &&
213                this.privateExponent.equals(other.privateExponent);
214     }
215     
216     /**
217      * Returns a hash code value for the object. 
218      *
219      * @return  a hash code value for this object.
220      * @see     java.lang.Object#equals(java.lang.Object)
221      * @see     java.util.Hashtable
222      */
223     public int hashCode() {
224         int result = 17;
225         result = 37*result + this.modulus.hashCode(); 
226         result = 37*result + this.privateExponent.hashCode(); 
227         return result;
228     }
229     
230     /**
231      * Returns a string representation of the object.
232      *
233      * @return  a string representation of the object.
234      */
235     public String toString() {
236         StringBuffer sb = new StringBuffer();
237         sb.append("[Modulus-Bit-Length: ");
238         sb.append(this.modulus.bitLength());
239         sb.append(", Modulus: ");
240         sb.append(this.modulus);
241         sb.append(", Private-Exponent: ");
242         sb.append(this.privateExponent);
243         sb.append(']');
244         return sb.toString();
245     }
246     
247     /**
248      * Writes this private key as two <code>BigInteger</code> objects to the
249      * stream for serialization. First the <code>modulus</code>, then the 
250      * <code>privateExponent</code>. 
251      *
252      * @param s the ObjectOutputStream.
253      * @throws IOException if there is something wrong with the
254      * ObjectOutputStream.
255      * @serialData First the <code>modulus</code> will be written as 
256      * <code>BigInteger</code> object, then the <code>privateExponent</code> 
257      * will be written as <code>BigInteger</code> too. 
258      * @see java.io.ObjectOutputStream
259      */    
260     private void writeObject(ObjectOutputStream s) throws IOException {
261         s.defaultWriteObject();
262         s.writeObject(this.modulus);
263         s.writeObject(this.privateExponent);
264     }     
265     
266     /**
267      * Reads this private key as two <code>BigInteger</code> objects from the
268      * stream for deserialization. First the <code>modulus</code>, then the 
269      * <code>privateExponent</code>. 
270      *
271      * Keep in mind this is a PSEUDOCONSTRUCTOR and you have to set
272      * do devensive copying, or use the new readUnshared and secondly
273      * you have to check all invariants, or your objects are immutable.
274      *
275      * @see java.io.ObjectInputStream
276      * @param s the ObjectInputStream.
277      * @throws IOException if there is something wrong with the
278      * ObjectInputStream.
279      * @throws ClassNotFoundException if the class can not be found.
280      * @throws InvalidObjectException if the streamm is tampered.
281      */    
282     private void readObject(ObjectInputStream s) 
283             throws IOException, ClassNotFoundException {
284         s.defaultReadObject();
285         BigInteger modulus = (BigInteger) s.readObject();
286         BigInteger privateExponent = (BigInteger) s.readObject();
287         
288         //We do all checks and setup the new object, that we read.
289         //May throws NullPointerException if one of the key data is null.
290         initialize(modulus, privateExponent);
291     }     
292     
293     
294     /**
295      * Returns the standard algorithm name for this key.
296      *
297      * @return the name of the algorithm associated with this key.
298      */
299     public String getAlgorithm() {
300         return "RSA";
301     }
302     
303     /**
304      * Returns the name of the primary encoding format of this key,
305      * or null if this key does not support encoding. 
306      *
307      * <p>We don't support encoding for this key, so this methods
308      * returns <code>null</code>.
309      *
310      * @return the primary encoding format of the key.
311      */
312     public String getFormat() {
313         return null;
314     }
315     
316     /**
317      * Returns the key in its primary encoding format, or null
318      * if this key does not support encoding.
319      *
320      * <p>We don't support encoding for this key, so this methods
321      * returns <code>null</code>.
322      *
323      * @return the encoded key, or null if the key does not support
324      * encoding.
325      */
326     public byte[] getEncoded() {
327         return null;
328     }
329     
330     /**
331      * Returns the modulus.
332      *
333      * @return the modulus
334      */
335     public BigInteger getModulus() {
336         return this.modulus;
337     }
338         
339     /**
340      * Returns the private exponent.
341      *
342      * @return the private exponent
343      */
344     public BigInteger getPrivateExponent() {
345         return this.privateExponent;
346     }
347     
348     /**
349      * This package private method will be used from the RSAKeyFactoryEngine.
350      *
351      * Return the matching key spec of this key.
352      *
353      * @return the matching key spec to this key.
354      * @see de.cscc.crypto.provider.RSAKeyFactoryEngine
355      */
356     KeySpec getKeySpec() {
357         return new RSAPrivateKeySpec(this.modulus, this.privateExponent);
358     }    
359 
360 }
361