1   /* $RCSfile: RSAPrivateCrtKeyImpl.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.RSAPrivateCrtKey;
39  import java.security.spec.KeySpec;
40  import java.security.spec.RSAPrivateCrtKeySpec;
41  
42  /** 
43   * RSAPrivateCrtKeyImpl 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 RSAPrivateCrtKeyImpl implements RSAPrivateCrtKey {
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 = 5115669147513835315L;
57      
58      /**
59       * RSA modulus. Must be non-null.
60       *
61       * @serial
62       */
63      private transient BigInteger modulus;
64  
65      /**
66       * RSA public exponent. Must be non-null.
67       *
68       * @serial
69       */
70      private transient BigInteger publicExponent;
71      
72      /**
73       * RSA private exponent. Must be non-null.
74       *
75       * @serial
76       */
77      private transient BigInteger privateExponent;
78      
79      /**
80       * RSA prime p of modulus n. Must be non-null.
81       *
82       * @serial
83       */
84      private transient BigInteger primeP;    
85      
86      /**
87       * RSA prime q of modulus n. Must be non-null.
88       *
89       * @serial
90       */
91      private transient BigInteger primeQ;    
92      
93      /**
94       * Exponent of prime p. Must be non-null.
95       * 
96       * <pre>
97       * primeExponentP = privateExponent mod (primeP - 1)
98       * </pre>
99       *
100      * @serial
101      */
102     private transient BigInteger primeExponentP;    
103     
104     /**
105      * Exponent of prime q. Must be non-null.
106      *
107      * <pre>
108      * primeExponentQ = privateExponent mod (primeQ - 1)
109      * </pre>
110      *
111      * @serial
112      */
113     private transient BigInteger primeExponentQ;
114     
115     /**
116      * CRT Coefficient. Must be non-null.
117      *
118      * <pre>
119      * crtCoefficient = primeQ^-1 mod primeP
120      * </pre>
121      *
122      * @serial
123      */
124     private transient BigInteger crtCoefficient;    
125     
126     /** 
127      * This package private constructor will be used from the 
128      * RSAKeyPairGeneratorEngine. 
129      *
130      * <p>Creates new RSAPrivateCrtKeyImpl  from two <code>BigInteger</code>
131      * values. There are no checks for specific invariants. A valid 
132      * <code>BigInteger</code> value is also a valid parameter.
133      *
134      * @param modulus The modulus of this private RSA key.
135      * @param publicExponent The public exponent of this private RSA key.
136      * @param privateExponent The private exponent of this private RSA key.
137      * @param primeP The prime factor p of modulus n of this private RSA key.
138      * @param primeQ The prime factor q of modulus n of this private RSA key.
139      * @param primeExponentP The exponent of prime factor p of this private RSA 
140      * key.
141      * @param primeExponentQ The exponent of prime factor q of this private RSA 
142      * key.
143      * @param crtCoefficient The CRT coefficient of prime q and p of this 
144      * private RSA key.
145      * @throws NullPointerException If one of the params is <code>null</code>.
146      * @see java.math.BigInteger
147      * @see de.cscc.crypto.provider.RSAKeyPairGeneratorEngine
148      */
149     RSAPrivateCrtKeyImpl(BigInteger modulus, BigInteger publicExponent,
150             BigInteger privateExponent, BigInteger primeP, BigInteger primeQ,
151             BigInteger primeExponentP, BigInteger primeExponentQ,
152             BigInteger crtCoefficient) {
153         //May throws NullPointerException if one of the key data is null.
154         initialize(modulus, 
155                    publicExponent, 
156                    privateExponent, 
157                    primeP, 
158                    primeQ, 
159                    primeExponentP, 
160                    primeExponentQ, 
161                    crtCoefficient);
162     }
163     
164     /** 
165      * This package private constructor will be used from the 
166      * RSAKeyFactoryEngine.
167      *
168      * <p>Creates new RSAPrivateCrtKeyImpl from an instance of a class that 
169      * implements the RSAPrivateCrtKey interface. May be this will be a class
170      * from a foreign provider, so we do all checks, which we have to do with
171      * pur BigIntegers.
172      *
173      * @param key existing key may from a foreign provider.
174      * @throws NullPointerException If <code>key</code> is <code>null</null> or
175      * one of keys 'key data' is <code>null</code>.
176      * @see de.cscc.crypto.provider.RSAKeyFactoryEngine
177      */    
178     RSAPrivateCrtKeyImpl(RSAPrivateCrtKey key) {
179         //Check params for null.
180         if (key == null) {
181             throw new NullPointerException("Parameter key is null.");
182         }
183         //May throws NullPointerException if one of the key data of a foreign
184         //provider key are null.
185         initialize(key.getModulus(), 
186                    key.getPublicExponent(), 
187                    key.getPrivateExponent(), 
188                    key.getPrimeP(), 
189                    key.getPrimeQ(), 
190                    key.getPrimeExponentP(), 
191                    key.getPrimeExponentQ(), 
192                    key.getCrtCoefficient());
193     }
194     
195     /** 
196      * This package private constructor will be used from the 
197      * RSAKeyFactoryEngine.
198      *
199      * <p>Creates new RSAPrivateCrtKeyImpl from an instance of a 
200      * RSAPrivateCrtKeySpec class. May be this class contains null references 
201      * instead BigInterger, so we do all checks, which we have to do with pur 
202      * BigIntegers.
203      *
204      * @param keySpec transparent specification that holds the key material.
205      * @throws NullPointerException If <code>keySpec</code> is <code>null</null>
206      * or one of the key specifakations 'key data' is <code>null</code>.
207      * @see de.cscc.crypto.provider.RSAKeyFactoryEngine
208      */    
209     RSAPrivateCrtKeyImpl(RSAPrivateCrtKeySpec keySpec) {
210         //Check params for null.
211         if (keySpec == null) {
212             throw new NullPointerException("Parameter keySpec is null.");
213         }
214         //May throws NullPointerException if one of the key data are null.
215         initialize(keySpec.getModulus(), 
216                    keySpec.getPublicExponent(), 
217                    keySpec.getPrivateExponent(), 
218                    keySpec.getPrimeP(), 
219                    keySpec.getPrimeQ(), 
220                    keySpec.getPrimeExponentP(), 
221                    keySpec.getPrimeExponentQ(), 
222                    keySpec.getCrtCoefficient());
223     }            
224     
225     /** 
226      * Private helper method, only used from the constructors and 
227      * pseudo-constructors like readObject.
228      *
229      * Initializes a new RSAPrivateCrtKeyImpl  from two <code>BigInteger</code>
230      * values. There are no checks for specific invariants. A valid 
231      * <code>BigInteger</code> value is also a valid parameter.
232      *
233      * @param modulus The modulus of this private RSA key.
234      * @param publicExponent The public exponent of this private RSA key.
235      * @param privateExponent The private exponent of this private RSA key.
236      * @param primeP The prime factor p of modulus n of this private RSA key.
237      * @param primeQ The prime factor q of modulus n of this private RSA key.
238      * @param primeExponentP The exponent of prime factor p of this private RSA 
239      * key.
240      * @param primeExponentQ The exponent of prime factor q of this private RSA 
241      * key.
242      * @param crtCoefficient The CRT coefficient of prime q and p of this 
243      * private RSA key.
244      * @throws NullPointerException If one of the params is <code>null</code>.
245      * @throws IllegalArgumentException if any Parameter is negative.
246      * @see java.math.BigInteger
247      */
248     private void initialize (BigInteger modulus, BigInteger publicExponent,
249             BigInteger privateExponent, BigInteger primeP, BigInteger primeQ,
250             BigInteger primeExponentP, BigInteger primeExponentQ,
251             BigInteger crtCoefficient) {
252         //Check params for null.
253         if (modulus == null) {
254             throw new NullPointerException("Parameter modulus is null.");
255         }
256         if (publicExponent == null) {
257             throw new NullPointerException("Parameter publicExponent is null.");
258         }        
259         if (privateExponent == null) {
260             throw new NullPointerException("Parameter privateExponent is null.");
261         }
262         if (primeP == null) {
263             throw new NullPointerException("Parameter primeP is null.");
264         }
265         if (primeQ == null) {
266             throw new NullPointerException("Parameter primeQ is null.");
267         }        
268         if (primeExponentP == null) {
269             throw new NullPointerException("Parameter primeExponentP is null.");
270         }        
271         if (primeExponentQ == null) {
272             throw new NullPointerException("Parameter primeExponentQ is null.");
273         }                
274         if (crtCoefficient == null) {
275             throw new NullPointerException("Parameter crtCoefficient is null.");
276         }        
277         
278         //Check params if the they real BigInteger, and not subclasses.
279         //If a param is a subclasses we construct a new real BigInteger from
280         //the specific param value.
281         if (modulus.getClass() != BigInteger.class) {
282             modulus = new BigInteger(modulus.toByteArray());
283         }
284         if (publicExponent.getClass() !=BigInteger.class) {
285             publicExponent = new BigInteger(publicExponent.toByteArray());
286         }        
287         if (privateExponent.getClass() !=BigInteger.class) {
288             privateExponent = new BigInteger(privateExponent.toByteArray());
289         }
290         if (primeP.getClass() !=BigInteger.class) {
291             primeP = new BigInteger(primeP.toByteArray());
292         }        
293         if (primeQ.getClass() !=BigInteger.class) {
294             primeQ = new BigInteger(primeQ.toByteArray());
295         }                
296         if (primeExponentP.getClass() !=BigInteger.class) {
297             primeExponentP = new BigInteger(primeExponentP.toByteArray());
298         }        
299         if (primeExponentQ.getClass() !=BigInteger.class) {
300             primeExponentQ = new BigInteger(primeExponentQ.toByteArray());
301         }                
302         if (crtCoefficient.getClass() !=BigInteger.class) {
303             crtCoefficient = new BigInteger(crtCoefficient.toByteArray());
304         }                        
305         
306         //Check if the params not negative
307         if (modulus.compareTo(BigInteger.ZERO) < 0) {
308             throw new IllegalArgumentException(
309             "Parameter modulus is negative. modulus: " + modulus);
310         }
311         if (publicExponent.compareTo(BigInteger.ZERO) < 0) {
312             throw new IllegalArgumentException(
313             "Parameter publicExponent is negative. publicExponent: " +
314             publicExponent);
315         }               
316         if (privateExponent.compareTo(BigInteger.ZERO) < 0) {
317             throw new IllegalArgumentException(
318             "Parameter privateExponent is negative. privateExponent: " +
319             privateExponent);
320         }                  
321         if (primeP.compareTo(BigInteger.ZERO) < 0) {
322             throw new IllegalArgumentException(
323             "Parameter primeP is negative. primeP: " + primeP);
324         }                          
325         if (primeQ.compareTo(BigInteger.ZERO) < 0) {
326             throw new IllegalArgumentException(
327             "Parameter primeQ is negative. primeQ: " + primeQ);
328         }
329         if (primeExponentP.compareTo(BigInteger.ZERO) < 0) {
330             throw new IllegalArgumentException(
331             "Parameter primeExponentP is negative. primeExponentP: " + 
332             primeExponentP);
333         }
334         if (primeExponentQ.compareTo(BigInteger.ZERO) < 0) {
335             throw new IllegalArgumentException(
336             "Parameter primeExponentQ is negative. primeExponentQ: " + 
337             primeExponentQ);
338         }
339         if (crtCoefficient.compareTo(BigInteger.ZERO) < 0) {
340             throw new IllegalArgumentException(
341             "Parameter crtCoefficient is negative. crtCoefficient: " + 
342             crtCoefficient);
343         }
344 
345         //We do only copy the references to the BigInteger objects,
346         //because BigInteger are immutable and this class too.
347         this.modulus = modulus;
348         this.publicExponent = publicExponent;
349         this.privateExponent = privateExponent;
350         this.primeP = primeP;
351         this.primeQ = primeQ;
352         this.primeExponentP = primeExponentP;
353         this.primeExponentQ = primeExponentQ;
354         this.crtCoefficient = crtCoefficient;
355     }
356     
357     /**
358      * Indicates whether some other object is "equal to" this one.
359      *
360      * @param   obj   the reference object with which to compare.
361      * @return  <code>true</code> if this object is the same as the obj
362      *         argument; <code>false</code> otherwise.
363      * @see     #hashCode()
364      * @see     java.util.Hashtable
365      */
366     public boolean equals(Object obj) {
367         //Only for performance.
368         if (this == obj) {
369             return true;
370         } 
371         
372         //If obj == null then instanceof returns false, see JLS 15.20.2
373         if (!(obj instanceof RSAPrivateCrtKeyImpl)) {
374             return false;
375         }
376         
377         RSAPrivateCrtKeyImpl other = (RSAPrivateCrtKeyImpl) obj;
378         return this.modulus.equals(other.modulus) 
379                 && this.publicExponent.equals(other.publicExponent)
380                 && this.privateExponent.equals(other.privateExponent)
381                 && this.primeP.equals(other.primeP)
382                 && this.primeQ.equals(other.primeQ)
383                 && this.primeExponentP.equals(other.primeExponentP)
384                 && this.primeExponentQ.equals(other.primeExponentQ)
385                 && this.crtCoefficient.equals(other.crtCoefficient);
386                 
387     }
388     
389     /**
390      * Returns a hash code value for the object. 
391      *
392      * @return  a hash code value for this object.
393      * @see     java.lang.Object#equals(java.lang.Object)
394      * @see     java.util.Hashtable
395      */
396     public int hashCode() {
397         int result = 17;
398         result = 37*result + this.modulus.hashCode();
399         result = 37*result + this.publicExponent.hashCode(); 
400         result = 37*result + this.privateExponent.hashCode(); 
401         result = 37*result + this.primeP.hashCode();
402         result = 37*result + this.primeQ.hashCode();
403         result = 37*result + this.primeExponentP.hashCode();
404         result = 37*result + this.primeExponentQ.hashCode();        
405         result = 37*result + this.crtCoefficient.hashCode();
406         return result;
407     }
408     
409     /**
410      * Returns a string representation of the object.
411      *
412      * @return  a string representation of the object.
413      */
414     public String toString() {
415         StringBuffer sb = new StringBuffer();
416         sb.append("[Modulus-Bit-Length: ");
417         sb.append(this.modulus.bitLength());
418         sb.append(", Modulus: ");
419         sb.append(this.modulus);
420         sb.append(", Public-Exponent: ");
421         sb.append(this.publicExponent);        
422         sb.append(", Private-Exponent: ");
423         sb.append(this.privateExponent);
424         sb.append(", Prime-P: ");
425         sb.append(this.primeP);
426         sb.append(", Prime-Q: ");
427         sb.append(this.primeQ);
428         sb.append(", Prime-Exponent-P: ");
429         sb.append(this.primeExponentP);
430         sb.append(", Prime-Exponent-Q: ");
431         sb.append(this.primeExponentQ);
432         sb.append(", CRT-Coefficient: ");
433         sb.append(this.crtCoefficient);        
434         sb.append(']');
435         return sb.toString();
436     }
437     
438     /**
439      * Writes this private key as two <code>BigInteger</code> objects to the
440      * stream for serialization. First the <code>modulus</code>, then the 
441      * <code>privateExponent</code>. 
442      *
443      * @param s the ObjectOutputStream.
444      * @throws IOException if there is something wrong with the
445      * ObjectOutputStream.
446      * @serialData The eight private <code>BigInteger</code> fields will be
447      * written in the following order: 
448      * <pre>
449      * 1. modulus
450      * 2. publicExponent
451      * 3. privateExponent
452      * 4. primeP
453      * 5. primeQ
454      * 6. primeExponentP
455      * 7. primeExponentQ
456      * 8. crtCoefficient
457      * </pre>
458      * @see java.io.ObjectOutputStream
459      */    
460     private void writeObject(ObjectOutputStream s) throws IOException {
461         s.defaultWriteObject();
462         s.writeObject(this.modulus);
463         s.writeObject(this.publicExponent);
464         s.writeObject(this.privateExponent);
465         s.writeObject(this.primeP);
466         s.writeObject(this.primeQ);
467         s.writeObject(this.primeExponentP);
468         s.writeObject(this.primeExponentQ);        
469         s.writeObject(this.crtCoefficient);
470     }     
471     
472     /**
473      * Reads this private key as eight <code>BigInteger</code> objects from the
474      * stream for deserialization.
475      *
476      * Keep in mind this is a PSEUDOCONSTRUCTOR and you have to set
477      * do devensive copying, or use the new readUnshared and secondly
478      * you have to check all invariants, or your objects are immutable.
479      *
480      * @see java.io.ObjectInputStream
481      * @param s the ObjectInputStream.
482      * @throws IOException if there is something wrong with the
483      * ObjectInputStream.
484      * @throws ClassNotFoundException if the class can not be found.
485      * @throws InvalidObjectException if the streamm is tampered.
486      */    
487     private void readObject(ObjectInputStream s) 
488             throws IOException, ClassNotFoundException {
489         s.defaultReadObject();
490         BigInteger modulus = (BigInteger) s.readObject();
491         BigInteger publicExponent = (BigInteger) s.readObject();        
492         BigInteger privateExponent = (BigInteger) s.readObject();
493         BigInteger primeP = (BigInteger) s.readObject();
494         BigInteger primeQ = (BigInteger) s.readObject();
495         BigInteger primeExponentP = (BigInteger) s.readObject();
496         BigInteger primeExponentQ = (BigInteger) s.readObject();        
497         BigInteger crtCoefficient = (BigInteger) s.readObject();
498         
499         //We do all checks and setup the new object, that we read.
500         //May throws NullPointerException if one of the key data is null.
501         initialize(modulus, publicExponent, privateExponent, primeP, primeQ, 
502                    primeExponentP, primeExponentQ, crtCoefficient);        
503     }     
504     
505     
506     /**
507      * Returns the standard algorithm name for this key.
508      *
509      * @return the name of the algorithm associated with this key.
510      */
511     public String getAlgorithm() {
512         return "RSA";
513     }
514     
515     /**
516      * Returns the name of the primary encoding format of this key,
517      * or null if this key does not support encoding. 
518      *
519      * <p>We don't support encoding for this key, so this methods
520      * returns <code>null</code>.
521      *
522      * @return the primary encoding format of the key.
523      */
524     public String getFormat() {
525         return null;
526     }
527     
528     /**
529      * Returns the key in its primary encoding format, or null
530      * if this key does not support encoding.
531      *
532      * <p>We don't support encoding for this key, so this methods
533      * returns <code>null</code>.
534      *
535      * @return the encoded key, or null if the key does not support
536      * encoding.
537      */
538     public byte[] getEncoded() {
539         return null;
540     }
541     
542     /**
543      * Returns the modulus.
544      *
545      * @return the modulus
546      */
547     public BigInteger getModulus() {
548         return this.modulus;
549     }
550     
551     /**
552      * Returns the public exponent.
553      *
554      * @return the public exponent
555      */
556     public BigInteger getPublicExponent() {
557         return this.publicExponent;
558     }    
559         
560     /**
561      * Returns the private exponent.
562      *
563      * @return the private exponent
564      */
565     public BigInteger getPrivateExponent() {
566         return this.privateExponent;
567     }
568     
569     /**
570      * Returns the primeP.
571      *
572      * @return the primeP
573      */
574     public BigInteger getPrimeP() {
575         return this.primeP;
576     }
577     
578     /**
579      * Returns the primeQ.
580      *
581      * @return the primeQ
582      */
583     public BigInteger getPrimeQ() {
584         return this.primeQ;
585     }
586 
587     /**
588      * Returns the primeExponentP.
589      *
590      * @return the primeExponentP
591      */
592     public BigInteger getPrimeExponentP() {
593         return this.primeExponentP;
594     }    
595     
596     /**
597      * Returns the primeExponentQ.
598      *
599      * @return the primeExponentQ
600      */
601     public BigInteger getPrimeExponentQ() {
602         return this.primeExponentQ;
603     }
604         
605     /**
606      * Returns the crtCoefficient.
607      *
608      * @return the crtCoefficient
609      */
610     public BigInteger getCrtCoefficient() {
611         return this.crtCoefficient;
612     }
613     
614     /**
615      * This package private method will be used from the RSAKeyFactoryEngine.
616      *
617      * Return the matching key spec of this key.
618      *
619      * @return the matching key spec to this key.
620      * @see de.cscc.crypto.provider.RSAKeyFactoryEngine
621      */
622     KeySpec getKeySpec() {
623         return new RSAPrivateCrtKeySpec(this.modulus, 
624                                         this.publicExponent, 
625                                         this.privateExponent, 
626                                         this.primeP, 
627                                         this.primeQ, 
628                                         this.primeExponentP, 
629                                         this.primeExponentQ, 
630                                         this.crtCoefficient);
631     }       
632 }
633