import java.math.BigInteger;

/** Calculate RSA public key pairs with a minimum number of
 *  required digits.
 *
 *  Taken from Core Web Programming from 
 *  Prentice Hall and Sun Microsystems Press,
 *  http://www.corewebprogramming.com/.
 *  &copy; 2001 Marty Hall and Larry Brown;
 *  may be freely used or adapted. 
 */
 
public class RSAKey {
  private static final BigInteger ONE = new BigInteger("1");

  // Determine the encryption and decryption key.
  // To encrypt an integer M, compute R = M^e mod N.
  // To decrypt the encrypted integer R, compute M = R^d mod N,
  // where e is the public key and d is the private key.
  // For a discussion of the algorithm see section 7.4.3 of
  // Weiss's Data Structures and Problem Solving with Java.
  public void computeKey(String strNumDigits) {
    BigInteger p, q, n, m, encrypt, decrypt;
    int numDigits = Integer.parseInt(strNumDigits);
    if (numDigits%2==1) {
      numDigits++;
    }
    do {
      p = Primes.nextPrime(Primes.random(numDigits/2));
      q = Primes.nextPrime(Primes.random(numDigits/2));

      n = p.multiply(q);
      m = (p.subtract(ONE)).multiply(q.subtract(ONE));

      // Find encryption key, relatively prime to m.
      encrypt = Primes.nextPrime(Primes.random(numDigits));
      while (!encrypt.gcd(m).equals(ONE)) {
        encrypt = Primes.nextPrime(encrypt);
      }
      // Decrypt key is multiplicative inverse of encrypt mod m.
      decrypt = encrypt.modInverse(m);
    // Ensure public and private key have size numDigits.
    }while ((decrypt.toString().length() != numDigits) || 
            (encrypt.toString().length() != numDigits) ||
            (n.toString().length() != numDigits));    
    System.out.println("\nN       => " + n);
    System.out.println("public  => " + encrypt);
    System.out.println("private => " + decrypt);
  }
}