Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
lare96 committed Sep 27, 2018
0 parents commit f47b2ea
Show file tree
Hide file tree
Showing 6 changed files with 211 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.idea/
out/
rsakeygen.iml
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rsakeygen
38 changes: 38 additions & 0 deletions src/io/luna/net/rsa/RSAKeyGen.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package io.luna.net.rsa;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.function.Consumer;

/**
* A {@link Consumer} implementation that will generate new RSA keys and store them in the local file system.
*
* @author lare96 <http://github.com/lare96>
*/
final class RSAKeyGen implements Consumer<String> {

/**
* The private RSA key file.
*/
private final Path privateFile = Paths.get("rsapriv.toml");

/**
* The public RSA key file.
*/
private final Path publicFile = Paths.get("rsapub.toml");

@Override
public void accept(String s) {
try {
RSAKeyPair keyPair = RSAKeyPair.newKeyPair();
keyPair.writeToFile(privateFile, publicFile);
} catch (NoSuchAlgorithmException | InvalidKeySpecException | IOException e) {
e.printStackTrace();
} finally {
RSAKeyGenMain.exit();
}
}
}
33 changes: 33 additions & 0 deletions src/io/luna/net/rsa/RSAKeyGenMain.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.luna.net.rsa;

/**
* The main class that will launch the terminal.
*
* @author lare96 <http://github.com/lare96>
*/
public final class RSAKeyGenMain {

/**
* The main method, the point of initialization.
*/
public static void main(String[] args) {
System.out.println("RSAKeyGen v1.0");
System.out.println("Type (y) to generate new keys.");
System.out.println("Keep in mind that doing this will overwrite existing keys.");

TerminalReader terminal = new TerminalReader();
terminal.awaitNextInputMatching("y", new RSAKeyGen());
}

/**
* Causes the application to gracefully exit.
*/
static void exit() {
System.out.println("The application will now exit.");
try {
Thread.sleep(3000);
} catch (InterruptedException ignored) {
}
System.exit(0);
}
}
94 changes: 94 additions & 0 deletions src/io/luna/net/rsa/RSAKeyPair.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package io.luna.net.rsa;

import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Path;
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;

/**
* A model representing a newly generated RSA public and private key pair.
*
* @author lare96 <http://github.com/lare96>
*/
final class RSAKeyPair {

/**
* Generates a new RSA key pair.
*
* @return The newly generated RSA key pair.
* @throws NoSuchAlgorithmException If the RSA algorithm is unavailable.
* @throws InvalidKeySpecException If the key specification is invalid.
*/
static RSAKeyPair newKeyPair() throws NoSuchAlgorithmException, InvalidKeySpecException {

// Initialize RSA key generator.
KeyPairGenerator rsaKeyGen = KeyPairGenerator.getInstance("RSA");
rsaKeyGen.initialize(1024);

// Retrieve modulus and exponent values for each key.
KeyPair keypair = rsaKeyGen.genKeyPair();
KeyFactory rsaKeyFactory = KeyFactory.getInstance("RSA");
RSAPrivateKeySpec privSpec = rsaKeyFactory.getKeySpec(keypair.getPrivate(), RSAPrivateKeySpec.class);
RSAPublicKeySpec pubSpec = rsaKeyFactory.getKeySpec(keypair.getPublic(), RSAPublicKeySpec.class);

// Store them!
return new RSAKeyPair(privSpec, pubSpec);
}

/**
* The private key.
*/
private final RSAPrivateKeySpec privateKey;

/**
* The public key.
*/
private final RSAPublicKeySpec publicKey;

/**
* Creates a new {@link RSAKeyPair}.
*
* @param privateKey The private key.
* @param publicKey The public key.
*/
private RSAKeyPair(RSAPrivateKeySpec privateKey, RSAPublicKeySpec publicKey) {
this.privateKey = privateKey;
this.publicKey = publicKey;
}

/**
* Writes the generated keys to the designated files.
*
* @param privateFile The file to store the private key.
* @param publicFile The file to store the public key.
* @throws IOException If any I/O errors occur while writing to the files.
*/
void writeToFile(Path privateFile, Path publicFile) throws IOException {
byte[] privateBytes = getBytes(privateKey.getModulus(), privateKey.getPrivateExponent());
byte[] publicBytes = getBytes(publicKey.getModulus(), publicKey.getPublicExponent());
Files.write(privateFile, privateBytes);
Files.write(publicFile, publicBytes);

System.out.println("RSA private and public keys successfully generated.");
}

/**
* Returns the bytes detailing the text to write to files.
*
* @param mod The modulus to write.
* @param exp The exponent to write.
* @return The private bytes.
*/
private byte[] getBytes(BigInteger mod, BigInteger exp) {
String writeString = "[key]\n" + "modulus = " + '"' + mod + '"' + '\n' +
"exponent = " + '"' + exp + '"';
return writeString.getBytes();
}
}
42 changes: 42 additions & 0 deletions src/io/luna/net/rsa/TerminalReader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package io.luna.net.rsa;

import java.util.Scanner;
import java.util.function.Consumer;

/**
* A model internally backed by a {@link Scanner} that will read input from the terminal.
*
* @author lare96 <http://github.com/lare96>
*/
final class TerminalReader {

/**
* The scanner for reading input.
*/
private final Scanner scanner = new Scanner(System.in);

/**
* Awaits the next input. Will block indefinitely.
*
* @return The input.
*/
private String awaitNextInput() {
return scanner.next();
}

/**
* Awaits the next input matching {@code expected}, then executes {@code onMatching} once the input
* matches. Will block indefinitely.
*
* @param expected The input to await.
* @param onMatching The action to execute when matching.
*/
void awaitNextInputMatching(String expected, Consumer<String> onMatching) {
for (; ; ) {
if (awaitNextInput().equals(expected)) {
onMatching.accept(expected);
break;
}
}
}
}

0 comments on commit f47b2ea

Please sign in to comment.