diff --git a/.gitignore b/.gitignore index 4e737abd..ff7341dc 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ *.iml /data/fs +/data/rsa.pem /data/savedGames /lib/ */target/ diff --git a/data/net.xml b/data/net.xml index 663d2811..8bd75431 100644 --- a/data/net.xml +++ b/data/net.xml @@ -1,9 +1,4 @@ - - 143690958001225849100503496893758066948984921380482659564113596152800934352119496873386875214251264258425208995167316497331786595942754290983849878549630226741961610780416197036711585670124061149988186026407785250364328460839202438651793652051153157765358767514800252431284681765433239888090564804146588087023 - 124425314960550024206991065332877157931472210939505789558012215720454903710618146200843877022273818555405810618059191162604008259757866640421952188957253368398733319663236323097864278319463888334484786055755767881706264786840339899269810859874287402892848784247637729987603089254067178011764721326471352835473 - - 80 43594 diff --git a/net/src/main/org/apollo/net/NetworkConstants.java b/net/src/main/org/apollo/net/NetworkConstants.java index 2be775f3..d91029f0 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. @@ -55,15 +62,6 @@ public final class NetworkConstants { throw new IOException("Root node name is not 'net'."); } - XmlNode rsa = net.getChild("rsa"); - Preconditions.checkState(rsa != null, "Root node must have a child named 'rsa'."); - - 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'."); - - RSA_MODULUS = new BigInteger(modulus.getValue()); - RSA_EXPONENT = new BigInteger(exponent.getValue()); - XmlNode ports = net.getChild("ports"); Preconditions.checkState(ports != null, "Root node must have a child named 'ports'."); @@ -76,6 +74,20 @@ public final class NetworkConstants { } catch (Exception exception) { throw new ExceptionInInitializerError(new IOException("Error parsing net.xml.", exception)); } + + try (PemReader pemReader = new PemReader(new FileReader("data/rsa.pem"))) { + PemObject pem = pemReader.readPemObject(); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pem.getContent()); + + Security.addProvider(new BouncyCastleProvider()); + KeyFactory factory = KeyFactory.getInstance("RSA", "BC"); + + 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.pem", 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..b66034f5 100644 --- a/util/pom.xml +++ b/util/pom.xml @@ -22,4 +22,5 @@ src/main src/test + \ 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