package me.ryleykimmel.brandywine.common.util;

import java.io.BufferedWriter;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Stopwatch;

public final class RsaKeygen {

	private static final Logger logger = LoggerFactory.getLogger(RsaKeygen.class);

	private static final String ALGORITHM = "RSA";
	private static final int BITS = 1024;

	public void generate() throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
		KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
		keyGen.initialize(BITS);

		KeyPair keyPair = keyGen.generateKeyPair();
		KeyFactory factory = KeyFactory.getInstance(ALGORITHM);

		RSAPublicKeySpec publicSpec = factory.getKeySpec(keyPair.getPublic(), RSAPublicKeySpec.class);
		RSAPrivateKeySpec privateSpec = factory.getKeySpec(keyPair.getPrivate(), RSAPrivateKeySpec.class);

		write("rsa_public", publicSpec.getModulus(), publicSpec.getPublicExponent());
		write("rsa_private", privateSpec.getModulus(), privateSpec.getPrivateExponent());
	}

	private void write(String prefix, BigInteger modulus, BigInteger exponent) throws IOException {
		Path path = Paths.get("data", prefix);
		
		// Create the directories if they don't exist.
		if (Files.notExists(path)) {
			Files.createDirectories(path);
		}

		try (BufferedWriter writer = Files.newBufferedWriter(path.resolve("rsa.key"), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
			writer.write("private static final BigInteger RSA_MODULUS = new BigInteger(\"");
			writer.write(modulus.toString());
			writer.write("\");");
			writer.newLine();

			writer.write("private static final BigInteger RSA_EXPONENT = new BigInteger(\"");
			writer.write(exponent.toString());
			writer.write("\");");
			writer.newLine();
		}
	}

	public static void main(String[] args) {
		RsaKeygen keygen = new RsaKeygen();

		Stopwatch stopwatch = Stopwatch.createStarted();
		try {
			keygen.generate();
		} catch (NoSuchAlgorithmException | InvalidKeySpecException | IOException cause) {
			logger.error("Unable to generate RSA keypair!", cause);
			System.exit(0);
		}

		logger.info("Took {}ms to generate public and private RSA keypairs.", stopwatch.stop().elapsed(TimeUnit.MILLISECONDS));
	}

}
@@ -685,39 +685,208 @@
 h;%0A%0A
-public final class RsaKeygen %7B%0A
+/**%0A * A utility class which generates RSA public and private keypairs.%0A * %0A * @author Ryley Kimmel %3Cryley.kimmel@live.com%3E%0A */%0Apublic final class RsaKeygen %7B%0A%0A%09/**%0A%09 * The logger for this class.%0A%09 */
 %0A%09pr
@@ -963,16 +963,54 @@
 lass);%0A%0A
+%09/**%0A%09 * The RSA algorithm name.%0A%09 */%0A
 %09private
@@ -1053,47 +1053,403 @@
 A%22;%0A
-%09private static final int BITS = 1024;%0A
+%0A%09/**%0A%09 * The modulus' length, specified in the number of bits.%0A%09 */%0A%09private static final int BITS = 1024;%0A%0A%09/**%0A%09 * Generates a public and private RSA keypair.%0A%09 * %0A%09 * @throws NoSuchAlgorithmException If the specified algorithm is not available in this environment.%0A%09 * @throws InvalidKeySpecException If any key cannot be processed.%0A%09 * @throws IOException If some I/O exception occurs.%0A%09 */
 %0A%09pu
@@ -1560,22 +1560,25 @@
 nerator 
-keyGen
+generator
  = KeyPa
@@ -1615,22 +1615,25 @@
 THM);%0A%09%09
-keyGen
+generator
 .initial
@@ -1658,24 +1658,24 @@
 air 
-keyP
+p
 air = 
-keyGen
+generator
 .gen
@@ -1792,36 +1792,33 @@
 tory.getKeySpec(
-keyP
+p
 air.getPublic(),
@@ -1900,12 +1900,9 @@
 pec(
-keyP
+p
 air.
@@ -2110,16 +2110,254 @@
 ));%0A%09%7D%0A%0A
+%09/**%0A%09 * Writes a RSA keypair to disk.%0A%09 * %0A%09 * @param root The root directory to write the RSA keypair.%0A%09 * @param modulus The RSA modulus.%0A%09 * @param exponent The RSA exponent.%0A%09 * @throws IOException If some I/O exception occurs.%0A%09 */%0A
 %09private
@@ -2375,22 +2375,20 @@
 (String 
-prefix
+root
 , BigInt
@@ -2479,19 +2479,15 @@
 a%22, 
-prefix
+root
 );%0A
-%09%09
 %0A%09%09/
@@ -3095,16 +3095,159 @@
 %09%09%7D%0A%09%7D%0A%0A
+%09/**%0A%09 * The entry point of this application which implements the command line-interface.%0A%09 *%0A%09 * @param args The command-line arguments.%0A%09 */%0A
 %09public 

Document RsaKeygen