| 
							
							
							
						 |  |  | @ -0,0 +1,450 @@ | 
		
	
		
			
				|  |  |  |  | package RSA; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | import java.math.BigInteger; | 
		
	
		
			
				|  |  |  |  | import java.util.Base64; | 
		
	
		
			
				|  |  |  |  | import java.util.Random; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | /** | 
		
	
		
			
				|  |  |  |  |  * @author Alexander Kimmig | 
		
	
		
			
				|  |  |  |  |  */ | 
		
	
		
			
				|  |  |  |  | public class RSA { | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * first prime number | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	private BigInteger p; | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * second prime number | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	private BigInteger q; | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * modulus p*q | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	private BigInteger N; | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * euler phi-function | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	private BigInteger phi; | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * exponent for encryption | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	private BigInteger e; | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * exponent for decryption | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	private BigInteger d; | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	private static final BigInteger B0 = new BigInteger("0"); | 
		
	
		
			
				|  |  |  |  | 	private static final BigInteger B1 = new BigInteger("1"); | 
		
	
		
			
				|  |  |  |  | 	private static final BigInteger B2 = new BigInteger("2"); | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * default constructor | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	public RSA() { | 
		
	
		
			
				|  |  |  |  | 		this.p = null; | 
		
	
		
			
				|  |  |  |  | 		this.q = null; | 
		
	
		
			
				|  |  |  |  | 		this.N = null; | 
		
	
		
			
				|  |  |  |  | 		this.phi = null; | 
		
	
		
			
				|  |  |  |  | 		this.e = null; | 
		
	
		
			
				|  |  |  |  | 		this.d = null; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * constructor with setting prime numbers manually | 
		
	
		
			
				|  |  |  |  | 	 * @param p first prime number | 
		
	
		
			
				|  |  |  |  | 	 * @param q second prime number | 
		
	
		
			
				|  |  |  |  | 	 * @param e exponent (coprime to phi) | 
		
	
		
			
				|  |  |  |  | 	 * @throws Exception  | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	public RSA(String p, String q, String e) throws Exception { | 
		
	
		
			
				|  |  |  |  | 		this.p = new BigInteger(p); | 
		
	
		
			
				|  |  |  |  | 		this.q = new BigInteger(q); | 
		
	
		
			
				|  |  |  |  | 		this.N = this.p.multiply(this.q); | 
		
	
		
			
				|  |  |  |  | 		this.phi = this.p.subtract(B1).multiply(this.q.subtract(B1)); | 
		
	
		
			
				|  |  |  |  | 		this.e = new BigInteger(e); | 
		
	
		
			
				|  |  |  |  | 		this.d = this.findd(); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * auto-generate a public-private keypair with 1024 bits | 
		
	
		
			
				|  |  |  |  | 	 * @throws Exception  | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	public void generatePair() throws Exception { this.generatePair(1024); } | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * auto-generate a public-private keypair | 
		
	
		
			
				|  |  |  |  | 	 * @param bits bitlength for prime numbers | 
		
	
		
			
				|  |  |  |  | 	 * @param ebits bitlength for encryption exponent | 
		
	
		
			
				|  |  |  |  | 	 * @throws Exception  | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	public void generatePair(int bits) throws Exception { | 
		
	
		
			
				|  |  |  |  | 		Random rand = new Random(); | 
		
	
		
			
				|  |  |  |  | 		int lengthp = (bits*(90+rand.nextInt(20))/200); | 
		
	
		
			
				|  |  |  |  | 		int lengthq = bits - lengthp; | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		this.p = new BigInteger(RSA.generatePrime(lengthp)); | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		while (this.N == null || this.N.bitLength() != bits) { | 
		
	
		
			
				|  |  |  |  | 			if (this.N != null && this.N.bitLength() < bits) lengthq++; | 
		
	
		
			
				|  |  |  |  | 			else if (this.N != null && this.N.bitLength() > bits) lengthq--; | 
		
	
		
			
				|  |  |  |  | 			 | 
		
	
		
			
				|  |  |  |  | 			this.q = new BigInteger(RSA.generatePrime(lengthq)); | 
		
	
		
			
				|  |  |  |  | 			this.N = this.p.multiply(this.q); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		this.phi = this.p.subtract(B1).multiply(this.q.subtract(B1)); | 
		
	
		
			
				|  |  |  |  | 		this.e = new BigInteger("65537"); | 
		
	
		
			
				|  |  |  |  | 		this.d = this.findd(); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * manually set private key | 
		
	
		
			
				|  |  |  |  | 	 * @param d exponent for decryption | 
		
	
		
			
				|  |  |  |  | 	 * @param N RSA modulus | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	public void setPrivate(String d, String N) { | 
		
	
		
			
				|  |  |  |  | 		this.d = new BigInteger(d); | 
		
	
		
			
				|  |  |  |  | 		this.N = new BigInteger(N); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * manually set public key | 
		
	
		
			
				|  |  |  |  | 	 * @param d exponent for encryption | 
		
	
		
			
				|  |  |  |  | 	 * @param N RSA modulus | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	public void setPublic(String e, String N) { | 
		
	
		
			
				|  |  |  |  | 		this.e = new BigInteger(e); | 
		
	
		
			
				|  |  |  |  | 		this.N = new BigInteger(N); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * helper-class for return-values for extended euclidean algorithm | 
		
	
		
			
				|  |  |  |  | 	 * @author Alexander Kimmig | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	private static class eeareturn { | 
		
	
		
			
				|  |  |  |  | 		BigInteger s; | 
		
	
		
			
				|  |  |  |  | 		BigInteger t; | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		public eeareturn(BigInteger s, BigInteger t) { | 
		
	
		
			
				|  |  |  |  | 			this.s = s; | 
		
	
		
			
				|  |  |  |  | 			this.t = t; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * executes the extended euclidean algorithm recursively | 
		
	
		
			
				|  |  |  |  | 	 * @param a first number | 
		
	
		
			
				|  |  |  |  | 	 * @param b second number | 
		
	
		
			
				|  |  |  |  | 	 * @return eeareturn with s and t | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	private static eeareturn eea(BigInteger a, BigInteger b) { | 
		
	
		
			
				|  |  |  |  | 		if (b.compareTo(a) > 0) { | 
		
	
		
			
				|  |  |  |  | 			eeareturn tmp = eea(b, a); | 
		
	
		
			
				|  |  |  |  | 			return new eeareturn(tmp.t, tmp.s); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		BigInteger q = a.divide(b); | 
		
	
		
			
				|  |  |  |  | 		BigInteger r = a.mod(b); | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		if (r.compareTo(B0) == 0) { | 
		
	
		
			
				|  |  |  |  | 			// System.out.println(a + ", " + b + ", " + q + ", " + r + ", 0, 1");
 | 
		
	
		
			
				|  |  |  |  | 			return new eeareturn(B0,B1); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		eeareturn alt = eea(b, r); | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		// System.out.println(a + ", " + b + ", " + q + ", " + r + ", " + alt.t + ", " + (alt.s-q*alt.t));
 | 
		
	
		
			
				|  |  |  |  | 		return new eeareturn(alt.t, alt.s.subtract(q.multiply(alt.t))); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * calculates the inverse d to e mod phi | 
		
	
		
			
				|  |  |  |  | 	 * @return exponent for decryption for given encryption-exponent | 
		
	
		
			
				|  |  |  |  | 	 * @throws Exception if phi not available | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	private BigInteger findd() throws Exception { | 
		
	
		
			
				|  |  |  |  | 		if (this.phi == null) { | 
		
	
		
			
				|  |  |  |  | 			throw new Exception("you don't have the prime numbers!"); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		return (RSA.eea(this.e,this.phi).s.add(this.phi)).mod(this.phi); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * calculates the inverse c to q mod p | 
		
	
		
			
				|  |  |  |  | 	 * @return coefficient | 
		
	
		
			
				|  |  |  |  | 	 * @throws Exception  | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	private BigInteger findcoefficient() throws Exception { | 
		
	
		
			
				|  |  |  |  | 		if (this.p == null) { | 
		
	
		
			
				|  |  |  |  | 			throw new Exception("you don't have the prime numbers!"); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		return (RSA.eea(this.q,this.p).s.add(this.p)).mod(this.p); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * calculating the power to a given modulus | 
		
	
		
			
				|  |  |  |  | 	 * @param b base | 
		
	
		
			
				|  |  |  |  | 	 * @param e exponent | 
		
	
		
			
				|  |  |  |  | 	 * @param mod modulus | 
		
	
		
			
				|  |  |  |  | 	 * @return the result | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	private static BigInteger modexp(BigInteger b, BigInteger e, BigInteger mod) { | 
		
	
		
			
				|  |  |  |  | 		BigInteger ret = B1; | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		while (e.compareTo(B0)>0) { | 
		
	
		
			
				|  |  |  |  | 			if (e.mod(B2).compareTo(B1) == 0) { | 
		
	
		
			
				|  |  |  |  | 				ret = ret.multiply(b).mod(mod); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			 | 
		
	
		
			
				|  |  |  |  | 			b = b.multiply(b).mod(mod); | 
		
	
		
			
				|  |  |  |  | 			 | 
		
	
		
			
				|  |  |  |  | 			e = e.divide(B2); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		return ret; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * encrypt a number | 
		
	
		
			
				|  |  |  |  | 	 * @param m number within a String (automatically convert to BigInteger) | 
		
	
		
			
				|  |  |  |  | 	 * @return the encypted number | 
		
	
		
			
				|  |  |  |  | 	 * @throws Exception if no public key available | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	public String encrypt(String m) throws Exception { | 
		
	
		
			
				|  |  |  |  | 		if (this.e == null || this.N == null) { | 
		
	
		
			
				|  |  |  |  | 			throw new Exception("you don't have a valid public key!"); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		return RSA.modexp(new BigInteger(m), this.e, this.N).toString(); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * decrypt a number | 
		
	
		
			
				|  |  |  |  | 	 * @param m number within a String (automatically convert to BigInteger) | 
		
	
		
			
				|  |  |  |  | 	 * @return the decrypted number | 
		
	
		
			
				|  |  |  |  | 	 * @throws Exception if no private key available | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	public String decrypt(String m) throws Exception { | 
		
	
		
			
				|  |  |  |  | 		if (this.d == null || this.N == null) { | 
		
	
		
			
				|  |  |  |  | 			throw new Exception("you don't have a valid private key!"); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		return RSA.modexp(new BigInteger(m), this.d, this.N).toString(); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * helper-function for printing public and private key | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	public String toString() { | 
		
	
		
			
				|  |  |  |  | 		String ret = ""; | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		if (this.e != null && this.N !=null) { | 
		
	
		
			
				|  |  |  |  | 			ret += "public key ("+this.e.toString()+","+this.N.toString()+")"; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		if (this.d != null && this.N !=null) { | 
		
	
		
			
				|  |  |  |  | 			if (ret != "") ret += "\n"; | 
		
	
		
			
				|  |  |  |  | 			ret += "private key ("+this.d.toString()+","+this.N.toString()+")"; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		if (ret == "") { | 
		
	
		
			
				|  |  |  |  | 			ret += "no key available!"; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		return ret; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * Miller-Rabin-Test for finding large prime numbers | 
		
	
		
			
				|  |  |  |  | 	 * @param n number to test for prime | 
		
	
		
			
				|  |  |  |  | 	 * @return true if probably prime | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	private static boolean isProbablyPrime(BigInteger n) { | 
		
	
		
			
				|  |  |  |  | 		int j = 0; | 
		
	
		
			
				|  |  |  |  | 		BigInteger d = n.subtract(B1); | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		if (n.compareTo(new BigInteger("5")) < 0) return false; | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		while(d.mod(B2).compareTo(B0) == 0) { | 
		
	
		
			
				|  |  |  |  | 			j++; | 
		
	
		
			
				|  |  |  |  | 			d = d.divide(B2); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		int[] _a = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71}; | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		for(int i=0; i<_a.length; i++) { | 
		
	
		
			
				|  |  |  |  | 			BigInteger a = new BigInteger(""+_a[i]); | 
		
	
		
			
				|  |  |  |  | 			if (a.compareTo(n.subtract(B2)) > 0) break; | 
		
	
		
			
				|  |  |  |  | 			 | 
		
	
		
			
				|  |  |  |  | 			boolean isPrime = false; | 
		
	
		
			
				|  |  |  |  | 			 | 
		
	
		
			
				|  |  |  |  | 			// System.out.println(a+"^"+d+"%"+n+"="+RSA.modexp(a, d, n));
 | 
		
	
		
			
				|  |  |  |  | 			if (RSA.modexp(a, d, n).compareTo(B1) == 0) isPrime = true; | 
		
	
		
			
				|  |  |  |  | 			 | 
		
	
		
			
				|  |  |  |  | 			if (isPrime) continue; | 
		
	
		
			
				|  |  |  |  | 			 | 
		
	
		
			
				|  |  |  |  | 			for(int r = 0; r<j; r++) { | 
		
	
		
			
				|  |  |  |  | 				BigInteger exp = d.multiply(B2.pow(r)); | 
		
	
		
			
				|  |  |  |  | 				// System.out.println(a+"^"+exp+"%"+n+"="+RSA.modexp(a, exp, n));
 | 
		
	
		
			
				|  |  |  |  | 				if (RSA.modexp(a, exp, n).compareTo(n.subtract(B1)) == 0) { | 
		
	
		
			
				|  |  |  |  | 					isPrime = true; | 
		
	
		
			
				|  |  |  |  | 				} | 
		
	
		
			
				|  |  |  |  | 				 | 
		
	
		
			
				|  |  |  |  | 				if (isPrime) break; | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			 | 
		
	
		
			
				|  |  |  |  | 			if (!isPrime) return false; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		return true; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * find a prime number | 
		
	
		
			
				|  |  |  |  | 	 * @param bits length of the prime number | 
		
	
		
			
				|  |  |  |  | 	 * @return prime number | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	public static String generatePrime(int bits) { | 
		
	
		
			
				|  |  |  |  | 		Random rand = new Random(); | 
		
	
		
			
				|  |  |  |  | 		BigInteger prime = new BigInteger(bits, rand); | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		// System.out.println(isProbablyPrime(new BigInteger("17")));
 | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		// System.out.println("trying " + prime);
 | 
		
	
		
			
				|  |  |  |  | 		while(!isProbablyPrime(prime)) { | 
		
	
		
			
				|  |  |  |  | 			prime = new BigInteger(bits, rand); | 
		
	
		
			
				|  |  |  |  | 			// System.out.println("trying " + prime);
 | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		return prime.toString(); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * generates the content for the public key file | 
		
	
		
			
				|  |  |  |  | 	 * @return String  | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	public String toPublicFileString() { | 
		
	
		
			
				|  |  |  |  | 		String ret = ""; | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		// add sequence
 | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			String seqdata = ""; | 
		
	
		
			
				|  |  |  |  | 			 | 
		
	
		
			
				|  |  |  |  | 			// add RSA identifier
 | 
		
	
		
			
				|  |  |  |  | 			seqdata += asn1field("06", "2A864886F70D010101"); | 
		
	
		
			
				|  |  |  |  | 			 | 
		
	
		
			
				|  |  |  |  | 			// add NULL
 | 
		
	
		
			
				|  |  |  |  | 			seqdata += "0500"; | 
		
	
		
			
				|  |  |  |  | 			 | 
		
	
		
			
				|  |  |  |  | 			ret += asn1field("30", seqdata); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		// add bit string
 | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			String bsdata = ""; | 
		
	
		
			
				|  |  |  |  | 			// add sequence with modulus and exponent
 | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				String seqdata = ""; | 
		
	
		
			
				|  |  |  |  | 				// add modulus
 | 
		
	
		
			
				|  |  |  |  | 				seqdata += asn1field("02", "00" + this.N.toString(16)); | 
		
	
		
			
				|  |  |  |  | 				 | 
		
	
		
			
				|  |  |  |  | 				// add exponent
 | 
		
	
		
			
				|  |  |  |  | 				seqdata += asn1field("02", this.e.toString(16)); | 
		
	
		
			
				|  |  |  |  | 				 | 
		
	
		
			
				|  |  |  |  | 				bsdata += asn1field("30", seqdata); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			 | 
		
	
		
			
				|  |  |  |  | 			ret += asn1field("03", "00" + bsdata); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		return "-----BEGIN PUBLIC KEY-----\n" + Base64.getEncoder().encodeToString(hex2byte(asn1field("30", ret))).replaceAll("(.{64})", "$1\n") + "\n-----END PUBLIC KEY-----"; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * generates the content for the private key file | 
		
	
		
			
				|  |  |  |  | 	 * @return String  | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	public String toPrivateFileString() throws Exception { | 
		
	
		
			
				|  |  |  |  | 		String ret = ""; | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		// add 0
 | 
		
	
		
			
				|  |  |  |  | 		ret += asn1field("02", "00"); | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		// add N
 | 
		
	
		
			
				|  |  |  |  | 		ret += asn1field("02", "00" + this.N.toString(16)); | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		// add e
 | 
		
	
		
			
				|  |  |  |  | 		ret += asn1field("02", this.e.toString(16)); | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		// add d
 | 
		
	
		
			
				|  |  |  |  | 		ret += asn1field("02", "00" + this.d.toString(16)); | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		// add p
 | 
		
	
		
			
				|  |  |  |  | 		ret += asn1field("02", "00" + this.p.toString(16)); | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		// add q
 | 
		
	
		
			
				|  |  |  |  | 		ret += asn1field("02", "00" + this.q.toString(16)); | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		// add d%(p-1)
 | 
		
	
		
			
				|  |  |  |  | 		ret += asn1field("02", "00" + this.d.mod(this.p.subtract(new BigInteger("1"))).toString(16)); | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		// add d%(q-1)
 | 
		
	
		
			
				|  |  |  |  | 		ret += asn1field("02", "00" + this.d.mod(this.q.subtract(new BigInteger("1"))).toString(16)); | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		// add coefficient
 | 
		
	
		
			
				|  |  |  |  | 		ret += asn1field("02", this.findcoefficient().toString(16)); | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		return "-----BEGIN RSA PRIVATE KEY-----\n" + Base64.getEncoder().encodeToString(hex2byte(asn1field("30", ret))).replaceAll("(.{64})", "$1\n") + "\n-----END RSA PRIVATE KEY-----"; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * generating a ASN 1 entry | 
		
	
		
			
				|  |  |  |  | 	 * @param type Type of the ASN 1 field | 
		
	
		
			
				|  |  |  |  | 	 * @param content Content of the ASN 1 field | 
		
	
		
			
				|  |  |  |  | 	 * @return the encoded string (hex-number as string) | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	private static String asn1field(String type, String content) { | 
		
	
		
			
				|  |  |  |  | 		String ret = type; | 
		
	
		
			
				|  |  |  |  | 		content = fill(content); | 
		
	
		
			
				|  |  |  |  | 		int length = content.length(); | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		if (length < 128) { | 
		
	
		
			
				|  |  |  |  | 			ret += fill(Integer.toHexString(length/2)).toUpperCase(); | 
		
	
		
			
				|  |  |  |  | 		} else { | 
		
	
		
			
				|  |  |  |  | 			String bytelength = fill(Integer.toHexString(length/2)); | 
		
	
		
			
				|  |  |  |  | 			int bytes = bytelength.length()/2; | 
		
	
		
			
				|  |  |  |  | 			ret += "8" + bytes + bytelength; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		ret += content.toUpperCase(); | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		return ret; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * helper-function for filling up a hex-string with a leading zero | 
		
	
		
			
				|  |  |  |  | 	 * @param s hex-string | 
		
	
		
			
				|  |  |  |  | 	 * @return | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	private static String fill(String s) { | 
		
	
		
			
				|  |  |  |  | 		if (s.length() % 2 == 0) return s; | 
		
	
		
			
				|  |  |  |  | 		return "0" + s; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	 | 
		
	
		
			
				|  |  |  |  | 	/** | 
		
	
		
			
				|  |  |  |  | 	 * convert a hex-string to a byte-array | 
		
	
		
			
				|  |  |  |  | 	 * @param hex | 
		
	
		
			
				|  |  |  |  | 	 * @return byte[] | 
		
	
		
			
				|  |  |  |  | 	 */ | 
		
	
		
			
				|  |  |  |  | 	private static byte[] hex2byte(String hex) { | 
		
	
		
			
				|  |  |  |  | 		byte[] b = new byte[hex.length()/2]; | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		for (int i=0; i<hex.length(); i+=2) { | 
		
	
		
			
				|  |  |  |  | 			b[i/2] = (byte) Integer.parseInt("" + hex.charAt(i)+hex.charAt(i+1), 16); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		 | 
		
	
		
			
				|  |  |  |  | 		return b; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } |