RSA.java
  1 package testrsa;
  2 
  3 
  4 
  5 import java.math.BigInteger;
  6 import java.security.KeyPair;
  7 import java.security.KeyPairGenerator;
  8 import java.security.NoSuchAlgorithmException;
  9 import java.util.Random;
 10 
 11 /**
 12  * Class RSA.
 13  * Provides math. methods for encryption, decryption, signing and verification.
 14  * If the keys are known there are constructors to use them,
 15  * but there is as well a method to generate a new pair of keys.
 16  * 
 17  * All parameters are BitIntegers, all return values are BitInteger or
 18  * arrays of BigInteger as this class provides the funcionality for
 19  * modular multiplicative inverse calculation.
 20  *
 21  * The modulus must be greater than the number to be encrypted but that should't
 22  * be a problem with the generated BigIntegers.
 23  *
 24  * @author Bernd Nussbaumer
 25  * @version $Revision: 0.1 $
 26  */
 27 public class RSA {
 28     
 29 /**
 30  * Variable to store the public exponent.
 31  */    
 32     private BigInteger pubExp = new BigInteger("0");    
 33     
 34 /**
 35  * Variable to store the public modulus.
 36  */    
 37     private BigInteger pubMod = new BigInteger("0");  
 38     
 39 /**
 40  * Variable to store the private key.
 41  */    
 42     private BigInteger privKey = new BigInteger("0");  
 43     
 44 /**
 45  * Key Length in bits.
 46  */    
 47     private int keyLength = 0;  
 48     
 49 
 50 /**
 51  * one is needed several times so there is a constant variable for it.
 52  */    
 53     private static final BigInteger one = new BigInteger("1"); 
 54     
 55 /**
 56  * BigIntegers can be generated as primes with a certainty. The higher the number
 57  * the slower the process. The probability a generated numer is prime is:
 58  * (1 - 1/2^certainty). So a value of 50 means a probability of 0.9999999999999991.
 59  */    
 60     private static final int certainty = 50;
 61 
 62 /**
 63  * Empty Constructor.
 64  */
 65     public RSA() {
 66         this.pubExp = new BigInteger("0");
 67         this.pubMod = new BigInteger("0");
 68         this.privKey = new BigInteger("0");
 69     }
 70 
 71 /**
 72  * Constructor with public exponent and public modulus.
 73  * Everybody can encrypt and verify a message with this.
 74  *
 75  * @param publicE the public exponent.
 76  * @param publicM the public modulus.
 77  */
 78     public RSA(BigInteger publicE, BigInteger publicM) {
 79         this.pubExp = publicE;
 80         this.pubMod = publicM;
 81         this.privKey = new BigInteger("0");
 82     }
 83 /**
 84  * Constructor with public exponent, public modulus and private key.
 85  * This is for the recipient who holds the private key.
 86  *
 87  * @param publicE the public exponent.
 88  * @param publicM the public modulus.
 89  * @param privateK the private key.
 90  */
 91     public RSA(BigInteger publicE, BigInteger publicM, BigInteger privateK) {
 92         this.pubExp = publicE;
 93         this.pubMod = publicM;
 94         this.privKey = privateK;
 95     }
 96 
 97 
 98 /**
 99  * Encryption with public exponent and public modulus.
100  * Modulus must be greater then the message.
101  *
102  * @param msg the message as BigInteger
103  * @return the ciphertext
104  */
105     public BigInteger encrypt(BigInteger msg) throws RsaException {
106         BigInteger cipher;
107         if (this.pubMod.compareTo(msg) == 1) {
108             cipher = msg.modPow(this.pubExp, this.pubMod);
109         } else {
110             throw new RsaException("Public modulus must be greater than the message!");
111         }
112         return cipher;
113     }
114 
115 /**
116  * Sign a message with private key and public modulus.
117  *
118  * @param msg the message as BigInteger
119  * @return the signature
120  */
121     public BigInteger sign(BigInteger msg) throws RsaException {
122         if (this.privKey.equals(new BigInteger("0"))) {
123            throw new RsaException("can't sign a message without private key.");
124         }
125         BigInteger signat;
126         signat = msg.modPow(this.privKey, this.pubMod);
127         return signat;
128     }
129 
130 
131 /**
132  * Verify a message using the public exponent
133  * and public modulus.
134  *
135  * @param signat the signature as BigInteger.
136  * @return the message.
137  */
138     public BigInteger verify(BigInteger signat) {
139         BigInteger veri;
140         veri = signat.modPow(this.pubExp, this.pubMod);
141         return veri;
142     }
143         
144 /**
145  * Decryption of a message. Only the owner of the private key
146  * is able to encrypt a message using the private key and the public modulus.
147  *
148  * Return value is m.  If this object does not
149  * have the private key, then we throw an exception.
150  *
151  * @param cipher the encrypted message as BigInteger.
152  * @return the decrypted message as BigInteger.
153  */
154     public BigInteger decrypt(BigInteger cipher) throws RsaException {
155         if (this.privKey.equals(new BigInteger("0"))) {
156            throw new RsaException("no decryption without private key.");
157         }
158         BigInteger msg;
159         msg = cipher.modPow(this.privKey, this.pubMod);
160         return msg;
161     }
162     
163 /**
164  * Generate a pair of keys.
165  * Private key, public exponent and public modulus are calculated and stored in
166  * privKey, pubExp and pubMod.
167  *
168  * Keys have a length between 512 and 2048 bits in 32bits increments.
169  *
170  * @param keyL the length of the key in bits. If keyL is zero then
171  * a random length for the key is generated with above restrictions.
172  *
173  * @return the length of the generated keys.
174  */
175     public int generateKeys(int keyL) {
176         BigInteger one = new BigInteger("1");
177         Random rand = new Random();
178         boolean found = false;
179         int keyLength = keyL;
180         if (keyL <= 0) {
181             keyLength = rand.nextInt(49);
182             keyLength = 512 + (keyLength * 32);
183         }
184         this.keyLength = keyLength;
185 
186         BigInteger p = new BigInteger("0");
187         BigInteger q = new BigInteger("0");
188         BigInteger p1 = new BigInteger("0");
189         BigInteger q1 = new BigInteger("0");
190         BigInteger phi = new BigInteger("0");
191         BigInteger e = new BigInteger("0");
192 
193 
194         p = new BigInteger(keyLength/2, certainty, new Random());   // searching first prime
195         q = new BigInteger(keyLength/2+1, certainty, new Random());   // searching second prime
196 
197         do {
198             e = new BigInteger(keyLength, certainty, new Random());    // searching prime for public exponent
199             p1 = p.subtract(one);
200             q1 = q.subtract(one);
201             phi = p1.multiply(q1);                          // totient
202             if ( phi.gcd(e).equals(one) ) {
203                 found = true;
204             }
205         } while (!found);                                   // public exponent has to be coprime of phi
206 
207         BigInteger pubMod = p.multiply(q);                  // public key modulus
208         BigInteger pubExp = e;                              // public key exponent
209         BigInteger privateK = pubExp.modInverse(phi);       // the private key
210 
211         this.privKey = privateK;
212         this.pubExp = pubExp;
213         this.pubMod = pubMod;
214 
215 
216         return this.keyLength;
217     }
218 
219 
220 /*
221  * Retrieve key length.
222  *
223  * @return the key length in bits as an integer.
224  */    
225     public int getKeyLength() {
226         return this.keyLength;
227     }
228     
229 /*
230  * Retrieve the public key.
231  *
232  * @return an array - at index 0 is the public exponent, at index 1 the public modulus.
233  */    
234     public BigInteger[] getPublicKey() {
235         BigInteger[] pubKey = new BigInteger[] {this.pubExp, this.pubMod};
236         return pubKey;
237     }
238 
239  /*
240  * Retrieve the public key.
241  *
242  * @return an array - at index 0 is the public exponent, at index 1 the public modulus.
243  */
244     public BigInteger getPrivateKey() {
245 
246         return this.privKey;
247     }
248     
249 
250 }
251