import java.math.BigInteger;
import java.util.Scanner;

public class RSATest {

	public static void main(String[] args) {
		//public key
		BigInteger n = BigInteger.valueOf(467);
		BigInteger r = BigInteger.valueOf(266243);
		
		//private
		BigInteger m = BigInteger.valueOf(251003);

		//Read a message from the user
		Scanner input = new Scanner(System.in);
		System.out.print("Enter a message: ");
		String msg = input.nextLine();
		//For each character
		for(int i = 0; i < msg.length(); i++) {
		//	convert it to a BigInteger
			BigInteger a = BigInteger.valueOf(msg.charAt(i));
		//  encode it via modPow
			BigInteger c = a.modPow(n, r);
			
		//  decode the cipher text via modPow
			BigInteger a2 = c.modPow(m, r);
			char c2 = (char)a2.intValue();
			
		//  print all that  out
			System.out.printf("%c %7s %7s %7s %c\n", msg.charAt(i),
					a, c, a2, c2);
			
		}
		
		//breaking RSA
		//1. factor r into p and q
		BigInteger p = null, q = null;
		
		for(p = BigInteger.valueOf(2);r.compareTo(p.multiply(p)) >= 0; 
				p = p.add(BigInteger.ONE)) {
			if(r.mod(p).equals(BigInteger.ZERO)) {
				q = r.divide(p);
				System.out.printf("p = %s, q=%s\n", p, q);
				break;
			}
		}
		
		//2. Find m
		//compute (p-1)*(q-1)
		BigInteger pq_1 = p.subtract(BigInteger.ONE)
						   .multiply(q.subtract(BigInteger.ONE));
		for(BigInteger k = BigInteger.ONE; 
				k.compareTo(r) < 0;
				k = k.add(BigInteger.ONE)){
			BigInteger temp = k.multiply(pq_1).add(BigInteger.ONE);
			if(temp.mod(n).equals(BigInteger.ZERO)) {
				System.out.printf("Private key is %s\n", temp.divide(n));
				break;
			}
		}
	}

}
