-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit f47b2ea
Showing
6 changed files
with
211 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.idea/ | ||
out/ | ||
rsakeygen.iml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
rsakeygen |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
} | ||
} |