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); } } }