ThreadedRSAKey.java Illustrates converting a method in an existing class from a single-threaded method to a multi-threaded method. In this example, RSAKey computes an RSA public-private key pair, where the key size has a specified number of digits. As large prime numbers require considerable CPU time, ThreadedRSAKey converts the original computeKey method in RSAKey to a multi-threaded method, thus allowing simultaneous (multithreaded) computation of multiple key pairs. Uses the following classes:
import java.io.*;
* RSAKey.java Computes RSA public-private key pairs of arbitrary length.
* Primes.java Generates large prime numbers.
/** An example of creating a background process for an
* originally nonthreaded, class method. Normally,
* the program flow will wait until computeKey is finished.
public class ThreadedRSAKey extends RSAKey implements Runnable {
// Store strNumDigits into the thread to prevent race
// conditions.
public void computeKey(String strNumDigits) {
RSAThread t = new RSAThread(this, strNumDigits);
t.start();
}
// Retrieve the stored strNumDigits and call the original
// method. Processing is now done in the background.
public void run() {
RSAThread t = (RSAThread)Thread.currentThread();
String strNumDigits = t.getStrDigits();
super.computeKey(strNumDigits);
}
public static void main(String[] args){
ThreadedRSAKey key = new ThreadedRSAKey();
for (int i=0; i " + n);
System.out.println("public => " + encrypt);
System.out.println("private => " + decrypt);
}
}
* Primes.java Generates large prime numbers.
***
import java.math.BigInteger;
/** A few utilities to generate a large random BigInteger,
* and find the next prime number above a given BigInteger.
public class Primes {
// Note that BigInteger.ZERO was new in JDK 1.2, and 1.1
// code is being used to support the most servlet engines.
private static final BigInteger ZERO = new BigInteger("0");
private static final BigInteger ONE = new BigInteger("1");
private static final BigInteger TWO = new BigInteger("2");
// Likelihood of false prime is less than 1/2^ERR_VAL
// Assumedly BigInteger uses the Miller-Rabin test or
// equivalent, and thus is NOT fooled by Carmichael numbers.
// See section 33.8 of Cormen et al. Introduction to
// Algorithms for details.
private static final int ERR_VAL = 100;
public static BigInteger nextPrime(BigInteger start) {
if (isEven(start))
start = start.add(ONE);
else
start = start.add(TWO);
if (start.isProbablePrime(ERR_VAL))
return(start);
else
return(nextPrime(start));
}
private static boolean isEven(BigInteger n) {
return(n.mod(TWO).equals(ZERO));
}
private static StringBuffer[] digits =
{ new StringBuffer("0"), new StringBuffer("1"),
new StringBuffer("2"), new StringBuffer("3"),
new StringBuffer("4"), new StringBuffer("5"),
new StringBuffer("6"), new StringBuffer("7"),
new StringBuffer("8"), new StringBuffer("9") };
private static StringBuffer randomDigit() {
int index = (int)Math.floor(Math.random() * 10);
return(digits[index]);
}
public static BigInteger random(int numDigits) {
StringBuffer s = new StringBuffer("");
for(int i=0; i 0)
numDigits = Integer.parseInt(args[0]);
else
numDigits = 150;
BigInteger start = random(numDigits);
for(int i=0; i<50; i++) {
start = nextPrime(start);
System.out.println("Prime " + i + " = " + start);
}
}
}
