mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-11-15 03:31:15 +03:00
[FEATURE] Support encrypted runtime
This commit is contained in:
parent
203fc638dc
commit
68d7c0a947
11 changed files with 180 additions and 22 deletions
|
@ -8,6 +8,10 @@
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
import pro.gravit.utils.helper.SecurityHelper;
|
import pro.gravit.utils.helper.SecurityHelper;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.CipherOutputStream;
|
||||||
|
import javax.crypto.NoSuchPaddingException;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
@ -16,6 +20,8 @@
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.SimpleFileVisitor;
|
import java.nio.file.SimpleFileVisitor;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -70,6 +76,10 @@ public void pushDir(Path dir, String targetDir, Map<String, byte[]> hashMap, boo
|
||||||
IOHelper.walk(dir, new RuntimeDirVisitor(output, hashMap, dir, targetDir), hidden);
|
IOHelper.walk(dir, new RuntimeDirVisitor(output, hashMap, dir, targetDir), hidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void pushEncryptedDir(Path dir, String targetDir, String aesHexKey, Map<String, byte[]> hashMap, boolean hidden) throws IOException {
|
||||||
|
IOHelper.walk(dir, new EncryptedRuntimeDirVisitor(output, aesHexKey, hashMap, dir, targetDir), hidden);
|
||||||
|
}
|
||||||
|
|
||||||
public void pushBytes(String filename, byte[] bytes) throws IOException {
|
public void pushBytes(String filename, byte[] bytes) throws IOException {
|
||||||
ZipEntry zip = IOHelper.newZipEntry(filename);
|
ZipEntry zip = IOHelper.newZipEntry(filename);
|
||||||
output.putNextEntry(zip);
|
output.putNextEntry(zip);
|
||||||
|
@ -178,4 +188,55 @@ private ZipEntry newEntry(String fileName) {
|
||||||
return newZipEntry(targetDir + IOHelper.CROSS_SEPARATOR + fileName);
|
return newZipEntry(targetDir + IOHelper.CROSS_SEPARATOR + fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final static class EncryptedRuntimeDirVisitor extends SimpleFileVisitor<Path> {
|
||||||
|
private final ZipOutputStream output;
|
||||||
|
private final Map<String, byte[]> hashs;
|
||||||
|
private final Path sourceDir;
|
||||||
|
private final String targetDir;
|
||||||
|
private final SecretKeySpec sKeySpec;
|
||||||
|
|
||||||
|
private EncryptedRuntimeDirVisitor(ZipOutputStream output, String aesKey, Map<String, byte[]> hashs, Path sourceDir, String targetDir) {
|
||||||
|
this.output = output;
|
||||||
|
this.hashs = hashs;
|
||||||
|
this.sourceDir = sourceDir;
|
||||||
|
this.targetDir = targetDir;
|
||||||
|
try {
|
||||||
|
byte[] key = SecurityHelper.fromHex(aesKey);
|
||||||
|
byte[] compatKey = SecurityHelper.getAESKey(key);
|
||||||
|
sKeySpec = new SecretKeySpec(compatKey, "AES");
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||||
|
byte[] digest = SecurityHelper.digest(SecurityHelper.DigestAlgorithm.MD5, file);
|
||||||
|
String fileName = IOHelper.toString(sourceDir.relativize(file));
|
||||||
|
if (hashs != null)
|
||||||
|
hashs.put(fileName, digest);
|
||||||
|
|
||||||
|
// Create zip entry and transfer contents
|
||||||
|
output.putNextEntry(newEntry(SecurityHelper.toHex(digest)));
|
||||||
|
|
||||||
|
|
||||||
|
Cipher cipher = null;
|
||||||
|
try {
|
||||||
|
cipher = Cipher.getInstance("AES");
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, sKeySpec);
|
||||||
|
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
IOHelper.transfer(file, new CipherOutputStream(output, cipher));
|
||||||
|
|
||||||
|
// Return result
|
||||||
|
return super.visitFile(file, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ZipEntry newEntry(String fileName) {
|
||||||
|
return newZipEntry(targetDir + IOHelper.CROSS_SEPARATOR + fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,10 +69,14 @@ public Path process(Path inputJar) throws IOException {
|
||||||
// map for guard
|
// map for guard
|
||||||
Map<String, byte[]> runtime = new HashMap<>(256);
|
Map<String, byte[]> runtime = new HashMap<>(256);
|
||||||
// Write launcher guard dir
|
// Write launcher guard dir
|
||||||
context.pushDir(server.launcherBinary.runtimeDir, Launcher.RUNTIME_DIR, runtime, false);
|
if(server.config.launcher.encryptRuntime) {
|
||||||
|
context.pushEncryptedDir(server.launcherBinary.runtimeDir, Launcher.RUNTIME_DIR, server.runtime.runtimeEncryptKey, runtime, false);
|
||||||
|
} else {
|
||||||
|
context.pushDir(server.launcherBinary.runtimeDir, Launcher.RUNTIME_DIR, runtime, false);
|
||||||
|
}
|
||||||
context.pushDir(server.launcherBinary.guardDir, Launcher.GUARD_DIR, runtime, false);
|
context.pushDir(server.launcherBinary.guardDir, Launcher.GUARD_DIR, runtime, false);
|
||||||
|
|
||||||
LauncherConfig launcherConfig = new LauncherConfig(server.config.netty.address, server.publicKey, runtime, server.config.projectName);
|
LauncherConfig launcherConfig = new LauncherConfig(server.config.netty.address, server.keyAgreementManager.ecdsaPublicKey, server.keyAgreementManager.rsaPublicKey, runtime, server.config.projectName);
|
||||||
context.pushFile(Launcher.CONFIG_FILE, launcherConfig);
|
context.pushFile(Launcher.CONFIG_FILE, launcherConfig);
|
||||||
postBuildHook.hook(context);
|
postBuildHook.hook(context);
|
||||||
}
|
}
|
||||||
|
@ -109,6 +113,8 @@ protected void initProps() {
|
||||||
properties.put("launcher.guardType", server.config.launcher.guardType);
|
properties.put("launcher.guardType", server.config.launcher.guardType);
|
||||||
properties.put("launchercore.env", server.config.env);
|
properties.put("launchercore.env", server.config.env);
|
||||||
properties.put("launcher.memory", server.config.launcher.memoryLimit);
|
properties.put("launcher.memory", server.config.launcher.memoryLimit);
|
||||||
|
if (server.runtime.runtimeEncryptKey == null) server.runtime.runtimeEncryptKey= SecurityHelper.randomStringAESKey();
|
||||||
|
properties.put("launcher.runtimeEncryptKey", server.runtime.runtimeEncryptKey);
|
||||||
properties.put("launcher.certificatePinning", server.config.launcher.certificatePinning);
|
properties.put("launcher.certificatePinning", server.config.launcher.certificatePinning);
|
||||||
properties.put("runtimeconfig.passwordEncryptKey", server.runtime.passwordEncryptKey);
|
properties.put("runtimeconfig.passwordEncryptKey", server.runtime.passwordEncryptKey);
|
||||||
String launcherSalt = SecurityHelper.randomStringToken();
|
String launcherSalt = SecurityHelper.randomStringToken();
|
||||||
|
|
|
@ -299,6 +299,7 @@ public static class LauncherConf {
|
||||||
public boolean stripLineNumbers;
|
public boolean stripLineNumbers;
|
||||||
public boolean deleteTempFiles;
|
public boolean deleteTempFiles;
|
||||||
public boolean certificatePinning;
|
public boolean certificatePinning;
|
||||||
|
public boolean encryptRuntime;
|
||||||
public int memoryLimit = 256;
|
public int memoryLimit = 256;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
public class LaunchServerRuntimeConfig {
|
public class LaunchServerRuntimeConfig {
|
||||||
public String passwordEncryptKey;
|
public String passwordEncryptKey;
|
||||||
|
public String runtimeEncryptKey;
|
||||||
public String oemUnlockKey;
|
public String oemUnlockKey;
|
||||||
public String registerApiKey;
|
public String registerApiKey;
|
||||||
public String clientCheckSecret;
|
public String clientCheckSecret;
|
||||||
|
@ -19,6 +20,7 @@ public void verify() {
|
||||||
|
|
||||||
public void reset() {
|
public void reset() {
|
||||||
passwordEncryptKey = SecurityHelper.randomStringToken();
|
passwordEncryptKey = SecurityHelper.randomStringToken();
|
||||||
|
runtimeEncryptKey = SecurityHelper.randomStringAESKey();
|
||||||
registerApiKey = SecurityHelper.randomStringToken();
|
registerApiKey = SecurityHelper.randomStringToken();
|
||||||
clientCheckSecret = SecurityHelper.randomStringToken();
|
clientCheckSecret = SecurityHelper.randomStringToken();
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
import java.lang.invoke.MethodType;
|
import java.lang.invoke.MethodType;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.security.interfaces.ECPublicKey;
|
import java.security.interfaces.ECPublicKey;
|
||||||
|
import java.security.interfaces.RSAPublicKey;
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
@ -28,7 +29,10 @@ public final class LauncherConfig extends StreamObject {
|
||||||
@LauncherInject("launcher.port")
|
@LauncherInject("launcher.port")
|
||||||
public final int clientPort;
|
public final int clientPort;
|
||||||
public final LauncherTrustManager trustManager;
|
public final LauncherTrustManager trustManager;
|
||||||
public final ECPublicKey publicKey;
|
@Deprecated
|
||||||
|
public ECPublicKey publicKey = null;
|
||||||
|
public final ECPublicKey ecdsaPublicKey;
|
||||||
|
public final RSAPublicKey rsaPublicKey;
|
||||||
public final Map<String, byte[]> runtime;
|
public final Map<String, byte[]> runtime;
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public final boolean isWarningMissArchJava;
|
public final boolean isWarningMissArchJava;
|
||||||
|
@ -40,8 +44,10 @@ public final class LauncherConfig extends StreamObject {
|
||||||
public final String secureCheckSalt;
|
public final String secureCheckSalt;
|
||||||
@LauncherInject("runtimeconfig.passwordEncryptKey")
|
@LauncherInject("runtimeconfig.passwordEncryptKey")
|
||||||
public final String passwordEncryptKey;
|
public final String passwordEncryptKey;
|
||||||
|
@LauncherInject("runtimeconfig.runtimeEncryptKey")
|
||||||
|
public final String runtimeEncryptKey;
|
||||||
@LauncherInject("launcher.address")
|
@LauncherInject("launcher.address")
|
||||||
public String address;
|
public final String address;
|
||||||
@LauncherInject("runtimeconfig.secretKeyClient")
|
@LauncherInject("runtimeconfig.secretKeyClient")
|
||||||
public String secretKeyClient;
|
public String secretKeyClient;
|
||||||
@LauncherInject("runtimeconfig.oemUnlockKey")
|
@LauncherInject("runtimeconfig.oemUnlockKey")
|
||||||
|
@ -52,10 +58,13 @@ public final class LauncherConfig extends StreamObject {
|
||||||
|
|
||||||
@LauncherInjectionConstructor
|
@LauncherInjectionConstructor
|
||||||
public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException {
|
public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException {
|
||||||
publicKey = SecurityHelper.toPublicECDSAKey(input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH));
|
ecdsaPublicKey = SecurityHelper.toPublicECDSAKey(input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH));
|
||||||
|
rsaPublicKey = SecurityHelper.toPublicRSAKey(input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH));
|
||||||
|
publicKey = ecdsaPublicKey;
|
||||||
secureCheckHash = null;
|
secureCheckHash = null;
|
||||||
secureCheckSalt = null;
|
secureCheckSalt = null;
|
||||||
passwordEncryptKey = null;
|
passwordEncryptKey = null;
|
||||||
|
runtimeEncryptKey = null;
|
||||||
projectName = null;
|
projectName = null;
|
||||||
clientPort = -1;
|
clientPort = -1;
|
||||||
secretKeyClient = null;
|
secretKeyClient = null;
|
||||||
|
@ -83,9 +92,12 @@ public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException
|
||||||
runtime = Collections.unmodifiableMap(localResources);
|
runtime = Collections.unmodifiableMap(localResources);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public LauncherConfig(String address, ECPublicKey publicKey, Map<String, byte[]> runtime, String projectName) {
|
public LauncherConfig(String address, ECPublicKey publicKey, Map<String, byte[]> runtime, String projectName) {
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.publicKey = publicKey;
|
this.publicKey = publicKey;
|
||||||
|
this.ecdsaPublicKey = this.publicKey;
|
||||||
|
this.rsaPublicKey = null;
|
||||||
this.runtime = Collections.unmodifiableMap(new HashMap<>(runtime));
|
this.runtime = Collections.unmodifiableMap(new HashMap<>(runtime));
|
||||||
this.projectName = projectName;
|
this.projectName = projectName;
|
||||||
this.clientPort = 32148;
|
this.clientPort = 32148;
|
||||||
|
@ -95,6 +107,24 @@ public LauncherConfig(String address, ECPublicKey publicKey, Map<String, byte[]>
|
||||||
secureCheckSalt = null;
|
secureCheckSalt = null;
|
||||||
secureCheckHash = null;
|
secureCheckHash = null;
|
||||||
passwordEncryptKey = null;
|
passwordEncryptKey = null;
|
||||||
|
runtimeEncryptKey = null;
|
||||||
|
trustManager = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LauncherConfig(String address, ECPublicKey ecdsaPublicKey, RSAPublicKey rsaPublicKey, Map<String, byte[]> runtime, String projectName) {
|
||||||
|
this.address = address;
|
||||||
|
this.ecdsaPublicKey = ecdsaPublicKey;
|
||||||
|
this.rsaPublicKey = rsaPublicKey;
|
||||||
|
this.runtime = Collections.unmodifiableMap(new HashMap<>(runtime));
|
||||||
|
this.projectName = projectName;
|
||||||
|
this.clientPort = 32148;
|
||||||
|
guardType = "no";
|
||||||
|
isWarningMissArchJava = true;
|
||||||
|
environment = LauncherEnvironment.STD;
|
||||||
|
secureCheckSalt = null;
|
||||||
|
secureCheckHash = null;
|
||||||
|
passwordEncryptKey = null;
|
||||||
|
runtimeEncryptKey = null;
|
||||||
trustManager = null;
|
trustManager = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,14 +133,16 @@ public LauncherConfig(String address, Map<String, byte[]> runtime, String projec
|
||||||
this.runtime = Collections.unmodifiableMap(new HashMap<>(runtime));
|
this.runtime = Collections.unmodifiableMap(new HashMap<>(runtime));
|
||||||
this.projectName = projectName;
|
this.projectName = projectName;
|
||||||
this.clientPort = 32148;
|
this.clientPort = 32148;
|
||||||
this.publicKey = null;
|
|
||||||
this.trustManager = trustManager;
|
this.trustManager = trustManager;
|
||||||
|
this.rsaPublicKey = null;
|
||||||
|
this.ecdsaPublicKey = null;
|
||||||
environment = env;
|
environment = env;
|
||||||
guardType = "no";
|
guardType = "no";
|
||||||
isWarningMissArchJava = true;
|
isWarningMissArchJava = true;
|
||||||
secureCheckSalt = null;
|
secureCheckSalt = null;
|
||||||
secureCheckHash = null;
|
secureCheckHash = null;
|
||||||
passwordEncryptKey = null;
|
passwordEncryptKey = null;
|
||||||
|
runtimeEncryptKey = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initModules(LauncherModulesManager modulesManager) {
|
public static void initModules(LauncherModulesManager modulesManager) {
|
||||||
|
@ -126,7 +158,8 @@ public static void initModules(LauncherModulesManager modulesManager) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(HOutput output) throws IOException {
|
public void write(HOutput output) throws IOException {
|
||||||
output.writeByteArray(publicKey.getEncoded(), SecurityHelper.CRYPTO_MAX_LENGTH);
|
output.writeByteArray(ecdsaPublicKey.getEncoded(), SecurityHelper.CRYPTO_MAX_LENGTH);
|
||||||
|
output.writeByteArray(rsaPublicKey.getEncoded(), SecurityHelper.CRYPTO_MAX_LENGTH);
|
||||||
|
|
||||||
// Write signed runtime
|
// Write signed runtime
|
||||||
Set<Map.Entry<String, byte[]>> entrySet = runtime.entrySet();
|
Set<Map.Entry<String, byte[]>> entrySet = runtime.entrySet();
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
public class OptionalDepend {
|
public class OptionalDepend {
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
public String name;
|
public String name;
|
||||||
|
@Deprecated
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
public OptionalType type;
|
public OptionalType type;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,8 +49,10 @@ public class OptionalFile {
|
||||||
public boolean isPreset;
|
public boolean isPreset;
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public transient Set<OptionalFile> dependenciesCount;
|
public transient Set<OptionalFile> dependenciesCount;
|
||||||
|
@Deprecated
|
||||||
private volatile transient Collection<BiConsumer<OptionalFile, Boolean>> watchList = null;
|
private volatile transient Collection<BiConsumer<OptionalFile, Boolean>> watchList = null;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public static OptionalType readType(HInput input) throws IOException {
|
public static OptionalType readType(HInput input) throws IOException {
|
||||||
int t = input.readInt();
|
int t = input.readInt();
|
||||||
OptionalType type;
|
OptionalType type;
|
||||||
|
@ -87,6 +89,7 @@ public int hashCode() {
|
||||||
return Objects.hash(name);
|
return Objects.hash(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public OptionalType getType() {
|
public OptionalType getType() {
|
||||||
return OptionalType.FILE;
|
return OptionalType.FILE;
|
||||||
}
|
}
|
||||||
|
@ -128,21 +131,25 @@ public void writeType(HOutput output) throws IOException {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public void registerWatcher(BiConsumer<OptionalFile, Boolean> watcher) {
|
public void registerWatcher(BiConsumer<OptionalFile, Boolean> watcher) {
|
||||||
if (watchList == null) watchList = ConcurrentHashMap.newKeySet();
|
if (watchList == null) watchList = ConcurrentHashMap.newKeySet();
|
||||||
watchList.add(watcher);
|
watchList.add(watcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public void removeWatcher(BiConsumer<OptionalFile, Boolean> watcher) {
|
public void removeWatcher(BiConsumer<OptionalFile, Boolean> watcher) {
|
||||||
if (watchList == null) return;
|
if (watchList == null) return;
|
||||||
watchList.remove(watcher);
|
watchList.remove(watcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public void clearAllWatchers() {
|
public void clearAllWatchers() {
|
||||||
if (watchList == null) return;
|
if (watchList == null) return;
|
||||||
watchList.clear();
|
watchList.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public void watchEvent(boolean isMark) {
|
public void watchEvent(boolean isMark) {
|
||||||
if (watchList == null) return;
|
if (watchList == null) return;
|
||||||
watchList.forEach((e) -> e.accept(this, isMark));
|
watchList.forEach((e) -> e.accept(this, isMark));
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import pro.gravit.launcher.LauncherNetworkAPI;
|
import pro.gravit.launcher.LauncherNetworkAPI;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public enum OptionalType {
|
public enum OptionalType {
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
FILE,
|
FILE,
|
||||||
|
|
|
@ -7,11 +7,17 @@
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
public class OptionalView {
|
public class OptionalView {
|
||||||
public Set<OptionalFile> enabled = new HashSet<>();
|
public Set<OptionalFile> enabled = new HashSet<>();
|
||||||
|
@Deprecated
|
||||||
public Map<OptionalFile, Set<OptionalFile>> dependenciesCountMap = new HashMap<>();
|
public Map<OptionalFile, Set<OptionalFile>> dependenciesCountMap = new HashMap<>();
|
||||||
|
public Map<OptionalFile, OptionalFileInstallInfo> installInfo = new HashMap<>();
|
||||||
public Set<OptionalFile> all;
|
public Set<OptionalFile> all;
|
||||||
|
public static class OptionalFileInstallInfo {
|
||||||
|
public boolean isManual;
|
||||||
|
}
|
||||||
|
|
||||||
public OptionalView(ClientProfile profile) {
|
public OptionalView(ClientProfile profile) {
|
||||||
this.all = profile.getOptional();
|
this.all = profile.getOptional();
|
||||||
|
@ -23,6 +29,7 @@ public OptionalView(ClientProfile profile) {
|
||||||
public OptionalView(OptionalView view) {
|
public OptionalView(OptionalView view) {
|
||||||
this.enabled = new HashSet<>(view.enabled);
|
this.enabled = new HashSet<>(view.enabled);
|
||||||
this.dependenciesCountMap = new HashMap<>(view.dependenciesCountMap);
|
this.dependenciesCountMap = new HashMap<>(view.dependenciesCountMap);
|
||||||
|
this.installInfo = new HashMap<>(view.installInfo);
|
||||||
this.all = view.all;
|
this.all = view.all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +69,7 @@ public Set<OptionalAction> getDisabledActions() {
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public void enable(OptionalFile file) {
|
public void enable(OptionalFile file) {
|
||||||
if (enabled.contains(file)) return;
|
if (enabled.contains(file)) return;
|
||||||
enabled.add(file);
|
enabled.add(file);
|
||||||
|
@ -80,6 +88,7 @@ public void enable(OptionalFile file) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public void disable(OptionalFile file) {
|
public void disable(OptionalFile file) {
|
||||||
if (!enabled.remove(file)) return;
|
if (!enabled.remove(file)) return;
|
||||||
file.watchEvent(false);
|
file.watchEvent(false);
|
||||||
|
@ -104,4 +113,52 @@ public void disable(OptionalFile file) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void enable(OptionalFile file, boolean manual, BiConsumer<OptionalFile, Boolean> callback) {
|
||||||
|
if(enabled.contains(file)) return;
|
||||||
|
if(callback != null) callback.accept(file, true);
|
||||||
|
OptionalFileInstallInfo installInfo = this.installInfo.get(file);
|
||||||
|
if(installInfo == null) {
|
||||||
|
installInfo = new OptionalFileInstallInfo();
|
||||||
|
this.installInfo.put(file, installInfo);
|
||||||
|
}
|
||||||
|
installInfo.isManual = manual;
|
||||||
|
if (file.dependencies != null) {
|
||||||
|
for (OptionalFile dep : file.dependencies) {
|
||||||
|
enable(dep, false, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (file.conflict != null) {
|
||||||
|
for (OptionalFile conflict : file.conflict) {
|
||||||
|
disable(conflict);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disable(OptionalFile file, BiConsumer<OptionalFile, Boolean> callback) {
|
||||||
|
if(!enabled.remove(file)) return;
|
||||||
|
if(callback != null) callback.accept(file, false);
|
||||||
|
for(OptionalFile dep : all) {
|
||||||
|
if(dep.dependencies != null && contains(file, dep.dependencies)) {
|
||||||
|
disable(dep, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (file.dependencies != null) {
|
||||||
|
for (OptionalFile dep : file.dependencies) {
|
||||||
|
OptionalFileInstallInfo installInfo = this.installInfo.get(dep);
|
||||||
|
if(installInfo != null && !installInfo.isManual) {
|
||||||
|
disable(file, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean contains(OptionalFile file, OptionalFile[] array) {
|
||||||
|
for(OptionalFile e : array) {
|
||||||
|
if(e == file) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package pro.gravit.utils.helper;
|
package pro.gravit.utils.helper;
|
||||||
|
|
||||||
import org.bouncycastle.jcajce.provider.asymmetric.RSA;
|
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.KeyGenerator;
|
import javax.crypto.KeyGenerator;
|
||||||
import javax.crypto.NoSuchPaddingException;
|
import javax.crypto.NoSuchPaddingException;
|
||||||
|
@ -489,7 +487,7 @@ public static Cipher newRSAEncryptCipher(RSAPublicKey publicKey) {
|
||||||
|
|
||||||
//AES
|
//AES
|
||||||
public static byte[] encrypt(String seed, byte[] cleartext) throws Exception {
|
public static byte[] encrypt(String seed, byte[] cleartext) throws Exception {
|
||||||
byte[] rawKey = getRawKey(seed.getBytes());
|
byte[] rawKey = getAESKey(seed.getBytes());
|
||||||
return encrypt(rawKey, cleartext);
|
return encrypt(rawKey, cleartext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,7 +495,7 @@ public static byte[] encrypt(String seed, String cleartext) throws Exception {
|
||||||
return encrypt(seed, cleartext.getBytes());
|
return encrypt(seed, cleartext.getBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] getRawKey(byte[] seed) throws Exception {
|
public static byte[] getAESKey(byte[] seed) throws Exception {
|
||||||
KeyGenerator kGen = KeyGenerator.getInstance("AES");
|
KeyGenerator kGen = KeyGenerator.getInstance("AES");
|
||||||
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
|
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
|
||||||
sr.setSeed(seed);
|
sr.setSeed(seed);
|
||||||
|
@ -521,7 +519,7 @@ public static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] decrypt(String seed, byte[] encrypted) throws Exception {
|
public static byte[] decrypt(String seed, byte[] encrypted) throws Exception {
|
||||||
return decrypt(getRawKey(seed.getBytes()), encrypted);
|
return decrypt(getAESKey(seed.getBytes()), encrypted);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] fromHex(String hexString) {
|
public static byte[] fromHex(String hexString) {
|
||||||
|
|
|
@ -215,16 +215,7 @@ public void run(String... args) throws Throwable {
|
||||||
|
|
||||||
public void updateLauncherConfig() {
|
public void updateLauncherConfig() {
|
||||||
|
|
||||||
LauncherConfig cfg = null;
|
LauncherConfig cfg = new LauncherConfig(config.address, null, null, new HashMap<>(), config.projectname);
|
||||||
try {
|
|
||||||
ECPublicKey publicKey = null;
|
|
||||||
if (IOHelper.isFile(publicKeyFile))
|
|
||||||
publicKey = SecurityHelper.toPublicECKey(IOHelper.read(publicKeyFile));
|
|
||||||
cfg = new LauncherConfig(config.address, publicKey, new HashMap<>(), config.projectname);
|
|
||||||
cfg.address = config.address;
|
|
||||||
} catch (InvalidKeySpecException | IOException e) {
|
|
||||||
LogHelper.error(e);
|
|
||||||
}
|
|
||||||
Launcher.setConfig(cfg);
|
Launcher.setConfig(cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue