mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-12-23 00:51:01 +03:00
Merge branch 'master' of github.com:GravitLauncher/Launcher
This commit is contained in:
commit
16f12d54f9
6 changed files with 81 additions and 36 deletions
|
@ -72,6 +72,12 @@ public void setProjectName(String name) {
|
||||||
body.append("\";");
|
body.append("\";");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSecretKey(String key) {
|
||||||
|
body.append("this.secretKeyClient = \"");
|
||||||
|
body.append(key);
|
||||||
|
body.append("\";");
|
||||||
|
}
|
||||||
|
|
||||||
public void setPort(int port) {
|
public void setPort(int port) {
|
||||||
body.append("this.port = ");
|
body.append("this.port = ");
|
||||||
body.append(port);
|
body.append(port);
|
||||||
|
|
|
@ -165,6 +165,7 @@ private void stdBuild() throws IOException {
|
||||||
jaConfigurator.setAddress(server.config.getAddress());
|
jaConfigurator.setAddress(server.config.getAddress());
|
||||||
jaConfigurator.setPort(server.config.port);
|
jaConfigurator.setPort(server.config.port);
|
||||||
jaConfigurator.setProjectName(server.config.projectName);
|
jaConfigurator.setProjectName(server.config.projectName);
|
||||||
|
jaConfigurator.setSecretKey(SecurityHelper.randomStringToken());
|
||||||
server.buildHookManager.registerAllClientModuleClass(jaConfigurator);
|
server.buildHookManager.registerAllClientModuleClass(jaConfigurator);
|
||||||
try (ZipInputStream input = new ZipInputStream(
|
try (ZipInputStream input = new ZipInputStream(
|
||||||
IOHelper.newInput(IOHelper.getResourceURL("Launcher.jar")))) {
|
IOHelper.newInput(IOHelper.getResourceURL("Launcher.jar")))) {
|
||||||
|
|
|
@ -109,7 +109,7 @@ public Params(byte[] launcherSign, Path assetDir, Path clientDir, PlayerProfile
|
||||||
}
|
}
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public Params(HInput input) throws IOException {
|
public Params(HInput input) throws Exception {
|
||||||
launcherSign = input.readByteArray(-SecurityHelper.RSA_KEY_LENGTH);
|
launcherSign = input.readByteArray(-SecurityHelper.RSA_KEY_LENGTH);
|
||||||
// Client paths
|
// Client paths
|
||||||
assetDir = IOHelper.toPath(input.readString(0));
|
assetDir = IOHelper.toPath(input.readString(0));
|
||||||
|
@ -122,7 +122,9 @@ public Params(HInput input) throws IOException {
|
||||||
}
|
}
|
||||||
// Client params
|
// Client params
|
||||||
pp = new PlayerProfile(input);
|
pp = new PlayerProfile(input);
|
||||||
accessToken = SecurityHelper.verifyToken(input.readASCII(-SecurityHelper.TOKEN_STRING_LENGTH));
|
byte[] encryptedAccessToken = input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH);
|
||||||
|
String accessTokenD = new String(SecurityHelper.decrypt(Launcher.getConfig().secretKeyClient.getBytes(),encryptedAccessToken));
|
||||||
|
accessToken = SecurityHelper.verifyToken(accessTokenD);
|
||||||
autoEnter = input.readBoolean();
|
autoEnter = input.readBoolean();
|
||||||
fullScreen = input.readBoolean();
|
fullScreen = input.readBoolean();
|
||||||
ram = input.readVarInt();
|
ram = input.readVarInt();
|
||||||
|
@ -143,7 +145,11 @@ public void write(HOutput output) throws IOException {
|
||||||
}
|
}
|
||||||
// Client params
|
// Client params
|
||||||
pp.write(output);
|
pp.write(output);
|
||||||
output.writeASCII(accessToken, -SecurityHelper.TOKEN_STRING_LENGTH);
|
try {
|
||||||
|
output.writeByteArray(SecurityHelper.encrypt(Launcher.getConfig().secretKeyClient.getBytes(),accessToken.getBytes()), SecurityHelper.CRYPTO_MAX_LENGTH);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogHelper.error(e);
|
||||||
|
}
|
||||||
output.writeBoolean(autoEnter);
|
output.writeBoolean(autoEnter);
|
||||||
output.writeBoolean(fullScreen);
|
output.writeBoolean(fullScreen);
|
||||||
output.writeVarInt(ram);
|
output.writeVarInt(ram);
|
||||||
|
@ -287,31 +293,25 @@ public static Process launch(
|
||||||
SignedObjectHolder<ClientProfile> profile, Params params, boolean pipeOutput) throws Throwable {
|
SignedObjectHolder<ClientProfile> profile, Params params, boolean pipeOutput) throws Throwable {
|
||||||
// Write params file (instead of CLI; Mustdie32 API can't handle command line > 32767 chars)
|
// Write params file (instead of CLI; Mustdie32 API can't handle command line > 32767 chars)
|
||||||
LogHelper.debug("Writing ClientLauncher params");
|
LogHelper.debug("Writing ClientLauncher params");
|
||||||
Path paramsFile = Files.createTempFile("ClientLauncherParams", ".bin");
|
|
||||||
CommonHelper.newThread("Client params writter", false, () ->
|
CommonHelper.newThread("Client params writter", false, () ->
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
try (ServerSocket socket = new ServerSocket()) {
|
try (ServerSocket socket = new ServerSocket()) {
|
||||||
socket.setReuseAddress(true);
|
|
||||||
socket.bind(new InetSocketAddress(SOCKET_HOST, SOCKET_PORT));
|
socket.setReuseAddress(true);
|
||||||
Socket client = socket.accept();
|
socket.bind(new InetSocketAddress(SOCKET_HOST, SOCKET_PORT));
|
||||||
try (HOutput output = new HOutput(client.getOutputStream())) {
|
Socket client = socket.accept();
|
||||||
params.write(output);
|
try (HOutput output = new HOutput(client.getOutputStream())) {
|
||||||
profile.write(output);
|
params.write(output);
|
||||||
assetHDir.write(output);
|
profile.write(output);
|
||||||
clientHDir.write(output);
|
assetHDir.write(output);
|
||||||
}
|
clientHDir.write(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (IOException e) {
|
||||||
LogHelper.error(e);
|
LogHelper.error(e);
|
||||||
try (HOutput output = new HOutput(IOHelper.newOutput(paramsFile))) {
|
|
||||||
params.write(output);
|
|
||||||
profile.write(output);
|
|
||||||
assetHDir.write(output);
|
|
||||||
clientHDir.write(output);
|
|
||||||
} catch (IOException e1) {
|
|
||||||
LogHelper.error(e1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
// Resolve java bin and set permissions
|
// Resolve java bin and set permissions
|
||||||
|
@ -356,7 +356,6 @@ public static Process launch(
|
||||||
//if(wrapper)
|
//if(wrapper)
|
||||||
//Collections.addAll(args, "-Djava.class.path=".concat(classPathString.toString())); // Add Class Path
|
//Collections.addAll(args, "-Djava.class.path=".concat(classPathString.toString())); // Add Class Path
|
||||||
Collections.addAll(args, ClientLauncher.class.getName());
|
Collections.addAll(args, ClientLauncher.class.getName());
|
||||||
Collections.addAll(args, paramsFile.toString());
|
|
||||||
|
|
||||||
// Print commandline debug message
|
// Print commandline debug message
|
||||||
LogHelper.debug("Commandline: " + args);
|
LogHelper.debug("Commandline: " + args);
|
||||||
|
@ -391,9 +390,6 @@ public static void main(String... args) throws Throwable {
|
||||||
checkJVMBitsAndVersion();
|
checkJVMBitsAndVersion();
|
||||||
JVMHelper.verifySystemProperties(ClientLauncher.class, true);
|
JVMHelper.verifySystemProperties(ClientLauncher.class, true);
|
||||||
LogHelper.printVersion("Client Launcher");
|
LogHelper.printVersion("Client Launcher");
|
||||||
// Resolve params file
|
|
||||||
VerifyHelper.verifyInt(args.length, l -> l >= 1, "Missing args: <paramsFile>");
|
|
||||||
Path paramsFile = IOHelper.toPath(args[0]);
|
|
||||||
// Read and delete params file
|
// Read and delete params file
|
||||||
LogHelper.debug("Reading ClientLauncher params");
|
LogHelper.debug("Reading ClientLauncher params");
|
||||||
Params params;
|
Params params;
|
||||||
|
@ -414,16 +410,8 @@ public static void main(String... args) throws Throwable {
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
LogHelper.error(ex);
|
LogHelper.error(ex);
|
||||||
try (HInput input = new HInput(IOHelper.newInput(paramsFile))) {
|
System.exit(-98);
|
||||||
params = new Params(input);
|
return;
|
||||||
profile = new SignedObjectHolder<>(input, publicKey, ClientProfile.RO_ADAPTER);
|
|
||||||
|
|
||||||
// Read hdirs
|
|
||||||
assetHDir = new SignedObjectHolder<>(input, publicKey, HashedDir::new);
|
|
||||||
clientHDir = new SignedObjectHolder<>(input, publicKey, HashedDir::new);
|
|
||||||
} finally {
|
|
||||||
Files.delete(paramsFile);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Launcher.profile = profile.object;
|
Launcher.profile = profile.object;
|
||||||
Launcher.modulesManager.initModules();
|
Launcher.modulesManager.initModules();
|
||||||
|
|
|
@ -5,6 +5,7 @@ public class AutogenConfig {
|
||||||
public String address;
|
public String address;
|
||||||
public int port;
|
public int port;
|
||||||
private boolean isInitModules;
|
private boolean isInitModules;
|
||||||
|
public String secretKeyClient;
|
||||||
|
|
||||||
AutogenConfig() {
|
AutogenConfig() {
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ public static AutogenConfig getAutogenConfig() {
|
||||||
public final InetSocketAddress address;
|
public final InetSocketAddress address;
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public final String projectname;
|
public final String projectname;
|
||||||
|
public String secretKeyClient;
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public final RSAPublicKey publicKey;
|
public final RSAPublicKey publicKey;
|
||||||
|
|
||||||
|
@ -47,6 +48,7 @@ public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException
|
||||||
ADDRESS_OVERRIDE == null ? localAddress : ADDRESS_OVERRIDE, config.port);
|
ADDRESS_OVERRIDE == null ? localAddress : ADDRESS_OVERRIDE, config.port);
|
||||||
publicKey = SecurityHelper.toPublicRSAKey(input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH));
|
publicKey = SecurityHelper.toPublicRSAKey(input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH));
|
||||||
projectname = config.projectname;
|
projectname = config.projectname;
|
||||||
|
secretKeyClient = config.secretKeyClient;
|
||||||
// Read signed runtime
|
// Read signed runtime
|
||||||
int count = input.readLength(0);
|
int count = input.readLength(0);
|
||||||
Map<String, byte[]> localResources = new HashMap<>(count);
|
Map<String, byte[]> localResources = new HashMap<>(count);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package ru.gravit.utils.helper;
|
package ru.gravit.utils.helper;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
@ -25,7 +26,10 @@
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.KeyGenerator;
|
||||||
import javax.crypto.NoSuchPaddingException;
|
import javax.crypto.NoSuchPaddingException;
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
import ru.gravit.launcher.LauncherAPI;
|
import ru.gravit.launcher.LauncherAPI;
|
||||||
|
|
||||||
|
@ -97,6 +101,7 @@ public byte[] verify(byte[] digest) {
|
||||||
// Certificate constants
|
// Certificate constants
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public static final String HEX = "0123456789abcdef";
|
public static final String HEX = "0123456789abcdef";
|
||||||
|
public static final byte[] NUMBERS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public static final SecureRandom secureRandom = new SecureRandom();
|
public static final SecureRandom secureRandom = new SecureRandom();
|
||||||
|
@ -463,4 +468,46 @@ public static String verifyToken(String token) {
|
||||||
|
|
||||||
private SecurityHelper() {
|
private SecurityHelper() {
|
||||||
}
|
}
|
||||||
|
//AES
|
||||||
|
public static byte[] encrypt(String seed, byte[] cleartext) throws Exception {
|
||||||
|
byte[] rawKey = getRawKey(seed.getBytes());
|
||||||
|
byte[] result = encrypt(rawKey, cleartext);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] encrypt(String seed, String cleartext) throws Exception {
|
||||||
|
return encrypt(seed, cleartext.getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] getRawKey(byte[] seed) throws Exception {
|
||||||
|
KeyGenerator kGen = KeyGenerator.getInstance("AES");
|
||||||
|
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
|
||||||
|
sr.setSeed(seed);
|
||||||
|
kGen.init(128, sr); // 192 and 256 bits may not be available
|
||||||
|
SecretKey sKey = kGen.generateKey();
|
||||||
|
return sKey.getEncoded();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
|
||||||
|
SecretKeySpec sKeySpec = new SecretKeySpec(raw, "AES");
|
||||||
|
Cipher cipher = Cipher.getInstance("AES");
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, sKeySpec);
|
||||||
|
return cipher.doFinal(clear);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
|
||||||
|
SecretKeySpec sKeySpec = new SecretKeySpec(raw, "AES");
|
||||||
|
Cipher cipher = Cipher.getInstance("AES");
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, sKeySpec);
|
||||||
|
return cipher.doFinal(encrypted);
|
||||||
|
}
|
||||||
|
public static byte[] HexToByte(String hexString) {
|
||||||
|
int len = hexString.length() / 2;
|
||||||
|
byte[] result = new byte[len];
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue