From ce28ac40578581779db6b49571269ec407ea2ddc Mon Sep 17 00:00:00 2001 From: Gravit Date: Wed, 16 Oct 2019 16:38:44 +0700 Subject: [PATCH] =?UTF-8?q?[FEATURE]=20=D0=BF=D0=B5=D1=80=D0=B5=D1=85?= =?UTF-8?q?=D0=BE=D0=B4=20=D0=BD=D0=B0=20EC=20=D0=BA=D0=BB=D1=8E=D1=87?= =?UTF-8?q?=D0=B8.=20=D0=9E=D1=82=D0=BA=D0=B0=D0=B7=20=D0=BE=D1=82=20RSA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pro/gravit/launchserver/LaunchServer.java | 11 +- .../launchserver/LaunchServerBuilder.java | 10 +- .../launchserver/LaunchServerStarter.java | 32 ++-- .../binary/LauncherConfigurator.java | 4 + .../binary/tasks/MainBuildTask.java | 1 + .../command/service/GetModulusCommand.java | 2 +- .../config/LaunchServerRuntimeConfig.java | 6 +- .../socket/response/auth/AuthResponse.java | 8 +- .../launchserver/StartLaunchServerTest.java | 9 +- Launcher/build.gradle | 1 + .../dialog/overlay/settings/settings.js | 2 +- .../pro/gravit/launcher/LauncherEngine.java | 15 +- .../launcher/client/FunctionalBridge.java | 9 + .../launcher/guard/LauncherGravitGuard.java | 2 +- .../launcher/guard/LauncherWrapperGuard.java | 2 +- .../pro/gravit/launcher/AutogenConfig.java | 1 + .../pro/gravit/launcher/LauncherConfig.java | 14 +- .../launcher/request/auth/AuthRequest.java | 12 +- ...thRSAPassword.java => AuthECPassword.java} | 4 +- LauncherCore/build.gradle | 1 + .../gravit/utils/helper/SecurityHelper.java | 179 +++++++----------- .../gravit/launcher/server/ServerWrapper.java | 4 +- modules | 2 +- 23 files changed, 164 insertions(+), 167 deletions(-) rename LauncherAPI/src/main/java/pro/gravit/launcher/request/auth/password/{AuthRSAPassword.java => AuthECPassword.java} (72%) diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java index b13fe974..a891822f 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java @@ -13,6 +13,8 @@ import java.security.InvalidAlgorithmParameterException; import java.security.KeyPair; import java.security.NoSuchAlgorithmException; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; @@ -220,9 +222,9 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO public LaunchServerRuntimeConfig runtime; - public final RSAPublicKey publicKey; + public final ECPublicKey publicKey; - public final RSAPrivateKey privateKey; + public final ECPrivateKey privateKey; // Launcher binary public final JARLauncherBinary launcherBinary; @@ -279,7 +281,7 @@ public void collect() } } - public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, LaunchServerConfig config, LaunchServerRuntimeConfig runtimeConfig, LaunchServerConfigManager launchServerConfigManager, LaunchServerModulesManager modulesManager, RSAPublicKey publicKey, RSAPrivateKey privateKey, CommandHandler commandHandler) throws IOException, InvalidKeySpecException { + public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, LaunchServerConfig config, LaunchServerRuntimeConfig runtimeConfig, LaunchServerConfigManager launchServerConfigManager, LaunchServerModulesManager modulesManager, ECPublicKey publicKey, ECPrivateKey privateKey, CommandHandler commandHandler) throws IOException, InvalidKeySpecException { this.dir = directories.dir; this.env = env; this.config = config; @@ -306,9 +308,6 @@ public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, La modulesManager.invokeEvent(new NewLaunchServerInstanceEvent(this)); // Print keypair fingerprints - CRC32 crc = new CRC32(); - crc.update(publicKey.getModulus().toByteArray()); // IDEA говорит, что это Java 9 API. WTF? - LogHelper.subInfo("Modulus CRC32: 0x%08x", crc.getValue()); // Load class bindings. launcherEXEBinaryClass = defaultLauncherEXEBinaryClass; diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerBuilder.java b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerBuilder.java index 310ac179..030e1633 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerBuilder.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerBuilder.java @@ -1,6 +1,8 @@ package pro.gravit.launchserver; import java.nio.file.Path; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; @@ -16,8 +18,8 @@ public class LaunchServerBuilder { private LaunchServer.LaunchServerEnv env; private LaunchServerModulesManager modulesManager; private LaunchServer.LaunchServerDirectories directories = new LaunchServer.LaunchServerDirectories(); - private RSAPublicKey publicKey; - private RSAPrivateKey privateKey; + private ECPublicKey publicKey; + private ECPrivateKey privateKey; private LaunchServer.LaunchServerConfigManager launchServerConfigManager; public LaunchServerBuilder setConfig(LaunchServerConfig config) { @@ -55,12 +57,12 @@ public LaunchServerBuilder setDir(Path dir) { return this; } - public LaunchServerBuilder setPublicKey(RSAPublicKey publicKey) { + public LaunchServerBuilder setPublicKey(ECPublicKey publicKey) { this.publicKey = publicKey; return this; } - public LaunchServerBuilder setPrivateKey(RSAPrivateKey privateKey) { + public LaunchServerBuilder setPrivateKey(ECPrivateKey privateKey) { this.privateKey = privateKey; return this; } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerStarter.java b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerStarter.java index 344f71f3..040466bd 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerStarter.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerStarter.java @@ -7,9 +7,12 @@ import java.nio.file.Files; import java.nio.file.Path; import java.security.KeyPair; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; +import java.security.SecureRandom; +import java.security.Security; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import org.bouncycastle.jce.provider.BouncyCastleProvider; import pro.gravit.launcher.Launcher; import pro.gravit.launcher.hwid.HWIDProvider; import pro.gravit.launcher.modules.events.PreConfigPhase; @@ -35,8 +38,11 @@ import pro.gravit.utils.helper.LogHelper; import pro.gravit.utils.helper.SecurityHelper; +import javax.crypto.Cipher; + public class LaunchServerStarter { public static void main(String[] args) throws Exception { + Security.addProvider(new BouncyCastleProvider()); JVMHelper.checkStackTrace(LaunchServerStarter.class); JVMHelper.verifySystemProperties(LaunchServer.class, true); LogHelper.addOutput(IOHelper.WORKING_DIR.resolve("LaunchServer.log")); @@ -51,8 +57,8 @@ public static void main(String[] args) throws Exception { Path configFile, runtimeConfigFile; Path publicKeyFile =dir.resolve("public.key"); Path privateKeyFile = dir.resolve("private.key"); - RSAPublicKey publicKey; - RSAPrivateKey privateKey; + ECPublicKey publicKey; + ECPrivateKey privateKey; LaunchServerRuntimeConfig runtimeConfig; LaunchServerConfig config; @@ -84,19 +90,17 @@ public static void main(String[] args) throws Exception { LogHelper.warning("JLine2 isn't in classpath, using std"); } if (IOHelper.isFile(publicKeyFile) && IOHelper.isFile(privateKeyFile)) { - LogHelper.info("Reading RSA keypair"); - publicKey = SecurityHelper.toPublicRSAKey(IOHelper.read(publicKeyFile)); - privateKey = SecurityHelper.toPrivateRSAKey(IOHelper.read(privateKeyFile)); - if (!publicKey.getModulus().equals(privateKey.getModulus())) - throw new IOException("Private and public key modulus mismatch"); + LogHelper.info("Reading EC keypair"); + publicKey = SecurityHelper.toPublicECKey(IOHelper.read(publicKeyFile)); + privateKey = SecurityHelper.toPrivateECKey(IOHelper.read(privateKeyFile)); } else { - LogHelper.info("Generating RSA keypair"); - KeyPair pair = SecurityHelper.genRSAKeyPair(); - publicKey = (RSAPublicKey) pair.getPublic(); - privateKey = (RSAPrivateKey) pair.getPrivate(); + LogHelper.info("Generating EC keypair"); + KeyPair pair = SecurityHelper.genECKeyPair(new SecureRandom()); + publicKey = (ECPublicKey) pair.getPublic(); + privateKey = (ECPrivateKey) pair.getPrivate(); // Write key pair list - LogHelper.info("Writing RSA keypair list"); + LogHelper.info("Writing EC keypair list"); IOHelper.write(publicKeyFile, publicKey.getEncoded()); IOHelper.write(privateKeyFile, privateKey.getEncoded()); } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/binary/LauncherConfigurator.java b/LaunchServer/src/main/java/pro/gravit/launchserver/binary/LauncherConfigurator.java index 49e53c53..e1aac82e 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/binary/LauncherConfigurator.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/binary/LauncherConfigurator.java @@ -65,6 +65,10 @@ public void setAddress(String address) { setStringField("address", address); } + public void setPasswordEncryptKey(String pass) { + setStringField("passwordEncryptKey", pass); + } + public void setProjectName(String name) { setStringField("projectname", name); } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/binary/tasks/MainBuildTask.java b/LaunchServer/src/main/java/pro/gravit/launchserver/binary/tasks/MainBuildTask.java index f420cd7b..df570184 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/binary/tasks/MainBuildTask.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/binary/tasks/MainBuildTask.java @@ -134,6 +134,7 @@ public Path process(Path inputJar) throws IOException { launcherConfigurator.setGuardType(server.config.launcher.guardType); launcherConfigurator.setWarningMissArchJava(server.config.launcher.warningMissArchJava); launcherConfigurator.setEnv(server.config.env); + launcherConfigurator.setPasswordEncryptKey(server.runtime.passwordEncryptKey); String launcherSalt = SecurityHelper.randomStringToken(); byte[] launcherSecureHash = SecurityHelper.digest(SecurityHelper.DigestAlgorithm.SHA256, server.runtime.clientCheckSecret.concat(".").concat(launcherSalt)); diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/command/service/GetModulusCommand.java b/LaunchServer/src/main/java/pro/gravit/launchserver/command/service/GetModulusCommand.java index c40eda10..b7454ecc 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/command/service/GetModulusCommand.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/command/service/GetModulusCommand.java @@ -21,6 +21,6 @@ public String getUsageDescription() { @Override public void invoke(String... args) throws Exception { - LogHelper.info("You publickey modulus: %s", server.publicKey.getModulus().toString(16)); + //LogHelper.info("You publickey modulus: %s", server.publicKey.getModulus().toString(16)); } } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/config/LaunchServerRuntimeConfig.java b/LaunchServer/src/main/java/pro/gravit/launchserver/config/LaunchServerRuntimeConfig.java index 0e600258..7e1798f9 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/config/LaunchServerRuntimeConfig.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/config/LaunchServerRuntimeConfig.java @@ -4,18 +4,18 @@ import pro.gravit.utils.helper.SecurityHelper; public class LaunchServerRuntimeConfig { - public String clientToken; + public String passwordEncryptKey; public String oemUnlockKey; public String registerApiKey; public String clientCheckSecret; public void verify() { - if (clientToken == null) LogHelper.error("[RuntimeConfig] clientToken must not be null"); + if (passwordEncryptKey == null) LogHelper.error("[RuntimeConfig] passwordEncryptKey must not be null"); if (clientCheckSecret == null) { LogHelper.warning("[RuntimeConfig] clientCheckSecret must not be null"); clientCheckSecret = SecurityHelper.randomStringToken(); } } public void reset() { - clientToken = SecurityHelper.randomStringToken(); + passwordEncryptKey = SecurityHelper.randomStringToken(); registerApiKey = SecurityHelper.randomStringToken(); clientCheckSecret = SecurityHelper.randomStringToken(); } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/auth/AuthResponse.java b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/auth/AuthResponse.java index e4ec148a..7d03fb55 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/auth/AuthResponse.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/auth/AuthResponse.java @@ -14,7 +14,7 @@ import pro.gravit.launcher.profiles.ClientProfile; import pro.gravit.launcher.request.auth.AuthRequest; import pro.gravit.launcher.request.auth.password.AuthPlainPassword; -import pro.gravit.launcher.request.auth.password.AuthRSAPassword; +import pro.gravit.launcher.request.auth.password.AuthECPassword; import pro.gravit.launchserver.auth.AuthException; import pro.gravit.launchserver.auth.AuthProviderPair; import pro.gravit.launchserver.auth.hwid.HWIDException; @@ -59,11 +59,11 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti AuthProvider.authError("Don't skip Launcher Update"); return; } - if(password instanceof AuthRSAPassword) + if(password instanceof AuthECPassword) { try { - password = new AuthPlainPassword(IOHelper.decode(SecurityHelper.newRSADecryptCipher(server.privateKey). - doFinal(((AuthRSAPassword) password).password))); + password = new AuthPlainPassword(IOHelper.decode(SecurityHelper.decrypt(server.runtime.passwordEncryptKey + , ((AuthECPassword) password).password))); } catch (IllegalBlockSizeException | BadPaddingException ignored) { throw new AuthException("Password decryption error"); } diff --git a/LaunchServer/src/test/java/pro/gravit/launchserver/StartLaunchServerTest.java b/LaunchServer/src/test/java/pro/gravit/launchserver/StartLaunchServerTest.java index 4af453ca..d19ab520 100644 --- a/LaunchServer/src/test/java/pro/gravit/launchserver/StartLaunchServerTest.java +++ b/LaunchServer/src/test/java/pro/gravit/launchserver/StartLaunchServerTest.java @@ -3,6 +3,9 @@ import java.io.IOException; import java.nio.file.Path; import java.security.KeyPair; +import java.security.SecureRandom; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; @@ -35,9 +38,9 @@ public static void prepare() throws Exception Launcher.gsonManager.initGson(); LaunchServerRuntimeConfig runtimeConfig = new LaunchServerRuntimeConfig(); LaunchServerBuilder builder = new LaunchServerBuilder(); - KeyPair pair = SecurityHelper.genRSAKeyPair(); - RSAPublicKey publicKey = (RSAPublicKey) pair.getPublic(); - RSAPrivateKey privateKey = (RSAPrivateKey) pair.getPrivate(); + KeyPair pair = SecurityHelper.genECKeyPair(new SecureRandom()); + ECPublicKey publicKey = (ECPublicKey) pair.getPublic(); + ECPrivateKey privateKey = (ECPrivateKey) pair.getPrivate(); builder.setDir(dir) .setEnv(LaunchServer.LaunchServerEnv.TEST) .setConfig(config) diff --git a/Launcher/build.gradle b/Launcher/build.gradle index 4d368664..a989aea5 100644 --- a/Launcher/build.gradle +++ b/Launcher/build.gradle @@ -50,6 +50,7 @@ task javadocJar(type: Jar) { pack project(':LauncherAuthlib') bundle 'com.github.oshi:oshi-core:3.13.0' bundle 'org.apache.httpcomponents:httpclient:4.5.7' + bundle 'org.bouncycastle:bcprov-jdk15:1.46' pack 'io.netty:netty-codec-http:4.1.36.Final' pack 'org.ow2.asm:asm-tree:7.1' } diff --git a/Launcher/runtime/dialog/overlay/settings/settings.js b/Launcher/runtime/dialog/overlay/settings/settings.js index 514b5739..22c0c0a6 100644 --- a/Launcher/runtime/dialog/overlay/settings/settings.js +++ b/Launcher/runtime/dialog/overlay/settings/settings.js @@ -155,7 +155,7 @@ var settingsOverlay = { }, setPassword: function(password) { - var encrypted = SecurityHelper.newRSAEncryptCipher(Launcher.getConfig().publicKey).doFinal(IOHelper.encode(password)); + var encrypted = FunctionalBridge.encryptPassword(password); return encrypted; }, diff --git a/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java b/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java index a1556111..657de117 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java +++ b/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java @@ -1,12 +1,11 @@ package pro.gravit.launcher; +import java.security.*; import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; -import pro.gravit.launcher.client.ClientModuleManager; -import pro.gravit.launcher.client.DirBridge; -import pro.gravit.launcher.client.FunctionalBridge; -import pro.gravit.launcher.client.LauncherUpdateController; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import pro.gravit.launcher.client.*; import pro.gravit.launcher.client.events.ClientEngineInitPhase; import pro.gravit.launcher.client.events.ClientPreGuiPhase; import pro.gravit.launcher.guard.LauncherGuardManager; @@ -22,10 +21,9 @@ import pro.gravit.launcher.request.auth.RestoreSessionRequest; import pro.gravit.launcher.request.update.UpdateRequest; import pro.gravit.launcher.request.websockets.StandartClientWebSocketService; -import pro.gravit.utils.helper.CommonHelper; -import pro.gravit.utils.helper.EnvHelper; -import pro.gravit.utils.helper.JVMHelper; -import pro.gravit.utils.helper.LogHelper; +import pro.gravit.utils.helper.*; + +import javax.crypto.Cipher; public class LauncherEngine { @@ -36,6 +34,7 @@ public static void main(String... args) throws Throwable { //if(!LauncherAgent.isStarted()) throw new SecurityException("JavaAgent not set"); LogHelper.printVersion("Launcher"); LogHelper.printLicense("Launcher"); + Security.addProvider(new BouncyCastleProvider()); LauncherEngine.modulesManager = new ClientModuleManager(); LauncherConfig.getAutogenConfig().initModules(); diff --git a/Launcher/src/main/java/pro/gravit/launcher/client/FunctionalBridge.java b/Launcher/src/main/java/pro/gravit/launcher/client/FunctionalBridge.java index 560b5abe..2cdf51ab 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/client/FunctionalBridge.java +++ b/Launcher/src/main/java/pro/gravit/launcher/client/FunctionalBridge.java @@ -1,11 +1,13 @@ package pro.gravit.launcher.client; import java.nio.file.Path; +import java.util.Arrays; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import pro.gravit.launcher.Launcher; import pro.gravit.launcher.LauncherAPI; import pro.gravit.launcher.api.AuthService; import pro.gravit.launcher.events.request.AuthRequestEvent; @@ -19,7 +21,9 @@ import pro.gravit.launcher.managers.HasherStore; import pro.gravit.launcher.request.Request; import pro.gravit.utils.Version; +import pro.gravit.utils.helper.IOHelper; import pro.gravit.utils.helper.LogHelper; +import pro.gravit.utils.helper.SecurityHelper; public class FunctionalBridge { @LauncherAPI @@ -133,4 +137,9 @@ public static String getLauncherVersion() { Version.BUILD ); } + @LauncherAPI + public static byte[] encryptPassword(String string) throws Exception { + byte[] encode = IOHelper.encode(string); + return SecurityHelper.encrypt(Launcher.getConfig().passwordEncryptKey, encode); + } } diff --git a/Launcher/src/main/java/pro/gravit/launcher/guard/LauncherGravitGuard.java b/Launcher/src/main/java/pro/gravit/launcher/guard/LauncherGravitGuard.java index 30f24026..10735c83 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/guard/LauncherGravitGuard.java +++ b/Launcher/src/main/java/pro/gravit/launcher/guard/LauncherGravitGuard.java @@ -76,7 +76,7 @@ public void addCustomEnv(ClientLauncherContext context) { LauncherConfig config = Launcher.getConfig(); env.put("GUARD_BRIDGE", GravitGuardBridge.class.getName()); env.put("GUARD_USERNAME", context.playerProfile.username); - env.put("GUARD_PUBLICKEY", config.publicKey.getModulus().toString(16)); + //env.put("GUARD_PUBLICKEY", config.publicKey.getModulus().toString(16)); env.put("GUARD_PROJECTNAME", config.projectname); if (protectToken != null) env.put("GUARD_TOKEN", protectToken); diff --git a/Launcher/src/main/java/pro/gravit/launcher/guard/LauncherWrapperGuard.java b/Launcher/src/main/java/pro/gravit/launcher/guard/LauncherWrapperGuard.java index 01eccbc1..e6922146 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/guard/LauncherWrapperGuard.java +++ b/Launcher/src/main/java/pro/gravit/launcher/guard/LauncherWrapperGuard.java @@ -63,7 +63,7 @@ public void addCustomEnv(ClientLauncherContext context) { env.put("JAVA_HOME", System.getProperty("java.home")); LauncherConfig config = Launcher.getConfig(); env.put("GUARD_USERNAME", context.playerProfile.username); - env.put("GUARD_PUBLICKEY", config.publicKey.getModulus().toString(16)); + //env.put("GUARD_PUBLICKEY", config.publicKey.getModulus().toString(16)); env.put("GUARD_PROJECTNAME", config.projectname); if (protectToken != null) env.put("GUARD_TOKEN", protectToken); diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/AutogenConfig.java b/LauncherAPI/src/main/java/pro/gravit/launcher/AutogenConfig.java index 05edd785..290a1e38 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/AutogenConfig.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/AutogenConfig.java @@ -12,6 +12,7 @@ public class AutogenConfig { public String guardLicenseEncryptKey; public String secureCheckHash; public String secureCheckSalt; + public String passwordEncryptKey; public int env; public boolean isWarningMissArchJava; // 0 - Dev (дебаг включен по умолчанию, все сообщения) diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/LauncherConfig.java b/LauncherAPI/src/main/java/pro/gravit/launcher/LauncherConfig.java index 6019b49d..6b012e79 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/LauncherConfig.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/LauncherConfig.java @@ -1,6 +1,8 @@ package pro.gravit.launcher; import java.io.IOException; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.util.Collections; @@ -31,7 +33,7 @@ public static AutogenConfig getAutogenConfig() { public String secretKeyClient; public String oemUnlockKey; @LauncherAPI - public final RSAPublicKey publicKey; + public final ECPublicKey publicKey; @LauncherAPI public final Map runtime; @@ -46,12 +48,14 @@ public static AutogenConfig getAutogenConfig() { public final String secureCheckHash; public final String secureCheckSalt; + public final String passwordEncryptKey; @LauncherAPI public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException { - publicKey = SecurityHelper.toPublicRSAKey(input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH)); + publicKey = SecurityHelper.toPublicECKey(input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH)); secureCheckHash = config.secureCheckHash; secureCheckSalt = config.secureCheckSalt; + passwordEncryptKey = config.passwordEncryptKey; projectname = config.projectname; clientPort = config.clientPort; secretKeyClient = config.secretKeyClient; @@ -84,7 +88,7 @@ public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException } @LauncherAPI - public LauncherConfig(String address, RSAPublicKey publicKey, Map runtime, String projectname) { + public LauncherConfig(String address, ECPublicKey publicKey, Map runtime, String projectname) { this.address = address; this.publicKey = Objects.requireNonNull(publicKey, "publicKey"); this.runtime = Collections.unmodifiableMap(new HashMap<>(runtime)); @@ -99,10 +103,11 @@ public LauncherConfig(String address, RSAPublicKey publicKey, Map runtime) { + public LauncherConfig(String address, ECPublicKey publicKey, Map runtime) { this.address = address; this.publicKey = Objects.requireNonNull(publicKey, "publicKey"); this.runtime = Collections.unmodifiableMap(new HashMap<>(runtime)); @@ -117,6 +122,7 @@ public LauncherConfig(String address, RSAPublicKey publicKey, Map HEX.indexOf(ch) >= 0); } private static Cipher newCipher(String algo) { - // IDK Why, but collapsing catch blocks makes ProGuard generate invalid stackmap try { return Cipher.getInstance(algo); } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { @@ -206,6 +180,19 @@ private static Cipher newCipher(String algo) { } } + /** + * @param algo Cipher algo + * @return Cipher instance + * @throws SecurityException: JCE cannot authenticate the provider BC if BouncyCastle is in unsigned jar + */ + private static Cipher newBCCipher(String algo) { + try { + return Cipher.getInstance(algo, new BouncyCastleProvider()); + } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { + throw new InternalError(e); + } + } + public static MessageDigest newDigest(DigestAlgorithm algo) { VerifyHelper.verify(algo, a -> a != DigestAlgorithm.PLAIN, "PLAIN digest"); @@ -221,8 +208,8 @@ public static SecureRandom newRandom() { return new SecureRandom(); } - private static Cipher newRSACipher(int mode, RSAKey key) { - Cipher cipher = newCipher(RSA_CIPHER_ALGO); + private static Cipher newECCipher(int mode, ECKey key) { + Cipher cipher = newBCCipher(EC_CIPHER_ALGO); try { cipher.init(mode, (Key) key); } catch (InvalidKeyException e) { @@ -231,35 +218,24 @@ private static Cipher newRSACipher(int mode, RSAKey key) { return cipher; } - @LauncherAPI - public static Cipher newRSADecryptCipher(RSAPrivateKey key) { - return newRSACipher(Cipher.DECRYPT_MODE, key); - } - - @LauncherAPI - public static Cipher newRSAEncryptCipher(RSAPublicKey key) { - return newRSACipher(Cipher.ENCRYPT_MODE, key); - } - - private static KeyFactory newRSAKeyFactory() { + private static KeyFactory newECKeyFactory() { try { - return KeyFactory.getInstance(RSA_ALGO); + return KeyFactory.getInstance(EC_ALGO); } catch (NoSuchAlgorithmException e) { throw new InternalError(e); } } - private static Signature newRSASignature() { + private static Signature newECSignature() { try { - return Signature.getInstance(RSA_SIGN_ALGO); + return Signature.getInstance(EC_SIGN_ALGO); } catch (NoSuchAlgorithmException e) { throw new InternalError(e); } } - - public static Signature newRSASignSignature(RSAPrivateKey key) { - Signature signature = newRSASignature(); + public static Signature newECSignSignature(ECPrivateKey key) { + Signature signature = newECSignature(); try { signature.initSign(key); } catch (InvalidKeyException e) { @@ -269,8 +245,8 @@ public static Signature newRSASignSignature(RSAPrivateKey key) { } - public static Signature newRSAVerifySignature(RSAPublicKey key) { - Signature signature = newRSASignature(); + public static Signature newECVerifySignature(ECPublicKey key) { + Signature signature = newECSignature(); try { signature.initVerify(key); } catch (InvalidKeyException e) { @@ -394,9 +370,8 @@ public static String randomUsername(Random random) { return VerifyHelper.verifyUsername(prefix + new String(chars) + suffix); } - - public static byte[] sign(byte[] bytes, RSAPrivateKey privateKey) { - Signature signature = newRSASignSignature(privateKey); + public static byte[] sign(byte[] bytes, ECPrivateKey privateKey) { + Signature signature = newECSignSignature(privateKey); try { signature.update(bytes); return signature.sign(); @@ -405,23 +380,6 @@ public static byte[] sign(byte[] bytes, RSAPrivateKey privateKey) { } } - public static byte[] sign(InputStream input, RSAPrivateKey privateKey) throws IOException { - Signature signature = newRSASignSignature(privateKey); - updateSignature(input, signature); - try { - return signature.sign(); - } catch (SignatureException e) { - throw new InternalError(e); - } - } - - - public static byte[] sign(Path path, RSAPrivateKey privateKey) throws IOException { - try (InputStream input = IOHelper.newInput(path)) { - return sign(input, privateKey); - } - } - public static String toHex(byte[] bytes) { int offset = 0; @@ -436,13 +394,12 @@ public static String toHex(byte[] bytes) { return new String(hex); } - - public static RSAPrivateKey toPrivateRSAKey(byte[] bytes) throws InvalidKeySpecException { - return (RSAPrivateKey) newRSAKeyFactory().generatePrivate(new PKCS8EncodedKeySpec(bytes)); + public static ECPublicKey toPublicECKey(byte[] bytes) throws InvalidKeySpecException { + return (ECPublicKey) newECKeyFactory().generatePublic(new X509EncodedKeySpec(bytes)); } - public static RSAPublicKey toPublicRSAKey(byte[] bytes) throws InvalidKeySpecException { - return (RSAPublicKey) newRSAKeyFactory().generatePublic(new X509EncodedKeySpec(bytes)); + public static ECPrivateKey toPrivateECKey(byte[] bytes) throws InvalidKeySpecException { + return (ECPrivateKey) newECKeyFactory().generatePrivate(new PKCS8EncodedKeySpec(bytes)); } private static void updateSignature(InputStream input, Signature signature) throws IOException { @@ -456,34 +413,41 @@ private static void updateSignature(InputStream input, Signature signature) thro } - public static void verifySign(byte[] bytes, byte[] sign, RSAPublicKey publicKey) throws SignatureException { + public static void verifySign(byte[] bytes, byte[] sign, ECPublicKey publicKey) throws SignatureException { if (!isValidSign(bytes, sign, publicKey)) throw new SignatureException("Invalid sign"); } - public static void verifySign(InputStream input, byte[] sign, RSAPublicKey publicKey) throws SignatureException, IOException { + public static void verifySign(InputStream input, byte[] sign, ECPublicKey publicKey) throws SignatureException, IOException { if (!isValidSign(input, sign, publicKey)) throw new SignatureException("Invalid stream sign"); } - public static void verifySign(Path path, byte[] sign, RSAPublicKey publicKey) throws SignatureException, IOException { - if (!isValidSign(path, sign, publicKey)) - throw new SignatureException(String.format("Invalid file sign: '%s'", path)); - } - - - public static void verifySign(URL url, byte[] sign, RSAPublicKey publicKey) throws SignatureException, IOException { - if (!isValidSign(url, sign, publicKey)) - throw new SignatureException(String.format("Invalid URL sign: '%s'", url)); - } - - public static String verifyToken(String token) { return VerifyHelper.verify(token, SecurityHelper::isValidToken, String.format("Invalid token: '%s'", token)); } + public static Cipher newECDecryptCipher(ECPrivateKey privateKey) + { + try { + return newECCipher(Cipher.DECRYPT_MODE, privateKey); + } catch (SecurityException e) + { + throw new InternalError(e); + } + } + public static Cipher newECEncryptCipher(ECPublicKey publicKey) + { + try { + return newECCipher(Cipher.ENCRYPT_MODE, publicKey); + } catch (SecurityException e) + { + throw new InternalError(e); + } + } + private SecurityHelper() { } @@ -521,6 +485,9 @@ public static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception { cipher.init(Cipher.DECRYPT_MODE, sKeySpec); return cipher.doFinal(encrypted); } + public static byte[] decrypt(String seed, byte[] encrypted) throws Exception { + return decrypt( getRawKey(seed.getBytes()), encrypted); + } public static byte[] HexToByte(String hexString) { int len = hexString.length() / 2; diff --git a/ServerWrapper/src/main/java/pro/gravit/launcher/server/ServerWrapper.java b/ServerWrapper/src/main/java/pro/gravit/launcher/server/ServerWrapper.java index 3949e2ad..42602a1f 100644 --- a/ServerWrapper/src/main/java/pro/gravit/launcher/server/ServerWrapper.java +++ b/ServerWrapper/src/main/java/pro/gravit/launcher/server/ServerWrapper.java @@ -52,7 +52,7 @@ public ServerWrapper(Type type, Path configPath) { public boolean auth() { try { LauncherConfig cfg = Launcher.getConfig(); - AuthRequest request = new AuthRequest(config.login, SecurityHelper.newRSAEncryptCipher(cfg.publicKey).doFinal(IOHelper.encode(config.password)), config.auth_id, AuthRequest.ConnectTypes.SERVER); + AuthRequest request = new AuthRequest(config.login, SecurityHelper.newECEncryptCipher(cfg.publicKey).doFinal(IOHelper.encode(config.password)), config.auth_id, AuthRequest.ConnectTypes.SERVER); permissions = request.request().permissions; ProfilesRequestEvent result = new ProfilesRequest().request(); for (ClientProfile p : result.profiles) { @@ -190,7 +190,7 @@ public void updateLauncherConfig() { LauncherConfig cfg = null; try { - cfg = new LauncherConfig(config.address, SecurityHelper.toPublicRSAKey(IOHelper.read(publicKeyFile)), new HashMap<>(), config.projectname); + cfg = new LauncherConfig(config.address, SecurityHelper.toPublicECKey(IOHelper.read(publicKeyFile)), new HashMap<>(), config.projectname); cfg.isNettyEnabled = true; cfg.address = config.address; } catch (InvalidKeySpecException | IOException e) { diff --git a/modules b/modules index 960e178b..a770ac08 160000 --- a/modules +++ b/modules @@ -1 +1 @@ -Subproject commit 960e178bc658835dc8aff93ee51e10e52bc7afb5 +Subproject commit a770ac083f9e940122f888fa6ffd9e0485d3292b