diff --git a/.gitignore b/.gitignore
index 993de82c..ff7341dc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,7 +10,7 @@
*.iml
/data/fs
-/data/rsa.xml
+/data/rsa.pem
/data/savedGames
/lib/
*/target/
diff --git a/data/rsa.xml.dist b/data/rsa.xml.dist
deleted file mode 100644
index 22506b24..00000000
--- a/data/rsa.xml.dist
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/net/src/main/org/apollo/net/NetworkConstants.java b/net/src/main/org/apollo/net/NetworkConstants.java
index e16345f7..3de056ab 100644
--- a/net/src/main/org/apollo/net/NetworkConstants.java
+++ b/net/src/main/org/apollo/net/NetworkConstants.java
@@ -1,14 +1,21 @@
package org.apollo.net;
import java.io.FileInputStream;
+import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
-
-import org.apollo.util.xml.XmlNode;
-import org.apollo.util.xml.XmlParser;
+import java.security.KeyFactory;
+import java.security.Security;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.spec.PKCS8EncodedKeySpec;
import com.google.common.base.Preconditions;
+import org.apollo.util.xml.XmlNode;
+import org.apollo.util.xml.XmlParser;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.util.io.pem.PemObject;
+import org.bouncycastle.util.io.pem.PemReader;
/**
* Holds various network-related constants such as port numbers.
@@ -68,20 +75,18 @@ public final class NetworkConstants {
throw new ExceptionInInitializerError(new IOException("Error parsing net.xml.", exception));
}
- try (InputStream is = new FileInputStream("data/rsa.xml")) {
- XmlNode rsa = new XmlParser().parse(is);
- if (!rsa.getName().equals("rsa")) {
- throw new IOException("Root node name is not 'rsa'.");
- }
+ try (PemReader pemReader = new PemReader(new FileReader("data/rsa.pem"))) {
+ PemObject pem = pemReader.readPemObject();
+ PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pem.getContent());
- XmlNode modulus = rsa.getChild("modulus"), exponent = rsa.getChild("private-exponent");
- Preconditions.checkState(modulus != null && exponent != null, "Rsa node must have two children: 'modulus' and 'private-exponent'.");
+ Security.addProvider(new BouncyCastleProvider());
+ KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
- Preconditions.checkState(modulus.getValue() != null && exponent.getValue() != null, "Value missing for 'modulus' or 'private-exponent'");
- RSA_MODULUS = new BigInteger(modulus.getValue());
- RSA_EXPONENT = new BigInteger(exponent.getValue());
+ RSAPrivateKey privateKey = (RSAPrivateKey) factory.generatePrivate(keySpec);
+ RSA_MODULUS = privateKey.getModulus();
+ RSA_EXPONENT = privateKey.getPrivateExponent();
} catch (Exception exception) {
- throw new ExceptionInInitializerError(new IOException("Error parsing rsa.xml", exception));
+ throw new ExceptionInInitializerError(new IOException("Error parsing id_rsa", exception));
}
}
diff --git a/pom.xml b/pom.xml
index 4e28c1c5..3e768ffc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -81,6 +81,12 @@
0.9.5.2
+
+ org.bouncycastle
+ bcprov-jdk15on
+ 1.54
+
+
junit
junit
@@ -101,6 +107,7 @@
1.6.4
test
+
\ No newline at end of file
diff --git a/util/pom.xml b/util/pom.xml
index 2b15f1a9..f7cfefe1 100644
--- a/util/pom.xml
+++ b/util/pom.xml
@@ -22,4 +22,12 @@
src/main
src/test
+
+
+
+ org.bouncycastle
+ bcprov-jdk15on
+
+
+
\ No newline at end of file
diff --git a/util/src/main/org/apollo/util/tools/RsaKeyGenerator.java b/util/src/main/org/apollo/util/tools/RsaKeyGenerator.java
index 0f0285f2..5bfc37a4 100644
--- a/util/src/main/org/apollo/util/tools/RsaKeyGenerator.java
+++ b/util/src/main/org/apollo/util/tools/RsaKeyGenerator.java
@@ -1,45 +1,62 @@
package org.apollo.util.tools;
-import java.math.BigInteger;
-import java.security.SecureRandom;
-import java.util.Random;
+import java.io.FileWriter;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.Security;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.util.io.pem.PemObject;
+import org.bouncycastle.util.io.pem.PemWriter;
/**
* An RSA key generator.
*
* @author Graham
* @author Major
+ * @author Cube
*/
public final class RsaKeyGenerator {
/**
- * The bit count. Strongly recommended to be at least 2,048.
+ * The bit count.
+ * Note: 2048 bits and above are not compatible with the client without modifications
*/
- private static final int BIT_COUNT = 2_048;
+ private static final int BIT_COUNT = 1024;
+
+ /**
+ * The path to the private key file.
+ */
+ private static final String PRIVATE_KEY_FILE = "data/rsa.pem";
/**
* The entry point of the RsaKeyGenerator.
*
* @param args The application arguments.
*/
- public static void main(String[] args) {
- Random random = new SecureRandom();
+ public static void main(String[] args) throws Exception {
+ Security.addProvider(new BouncyCastleProvider());
- BigInteger publicKey = BigInteger.valueOf(65_537);
- BigInteger p, q, phi, modulus, privateKey;
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC");
+ keyPairGenerator.initialize(BIT_COUNT);
+ KeyPair keyPair = keyPairGenerator.generateKeyPair();
- do {
- p = BigInteger.probablePrime(BIT_COUNT / 2, random);
- q = BigInteger.probablePrime(BIT_COUNT / 2, random);
- phi = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE));
+ RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
+ RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
- modulus = p.multiply(q);
- privateKey = publicKey.modInverse(phi);
- } while (modulus.bitLength() != BIT_COUNT || privateKey.bitLength() != BIT_COUNT || !phi.gcd(publicKey).equals(BigInteger.ONE));
+ System.out.println("Place these keys in the client:");
+ System.out.println("--------------------");
+ System.out.println("public key: " + publicKey.getPublicExponent());
+ System.out.println("modulus: " + publicKey.getModulus());
- System.out.println("modulus: " + modulus);
- System.out.println("public key: " + publicKey);
- System.out.println("private key: " + privateKey);
+ try (PemWriter writer = new PemWriter(new FileWriter(PRIVATE_KEY_FILE))) {
+ writer.writeObject(new PemObject("RSA PRIVATE KEY", privateKey.getEncoded()));
+ } catch (Exception e) {
+ System.err.println("Failed to write private key to " + PRIVATE_KEY_FILE);
+ e.printStackTrace();
+ }
}
}
\ No newline at end of file