mirror of
https://github.com/GravitLauncher/Launcher
synced 2025-06-28 12:08:09 +03:00
[FEATURE] Implement HardwareVerificationFeatureAPI
This commit is contained in:
parent
a03de56dde
commit
f246ab697b
12 changed files with 269 additions and 126 deletions
|
@ -6,19 +6,14 @@
|
||||||
import pro.gravit.launcher.client.*;
|
import pro.gravit.launcher.client.*;
|
||||||
import pro.gravit.launcher.core.api.LauncherAPI;
|
import pro.gravit.launcher.core.api.LauncherAPI;
|
||||||
import pro.gravit.launcher.core.api.LauncherAPIHolder;
|
import pro.gravit.launcher.core.api.LauncherAPIHolder;
|
||||||
import pro.gravit.launcher.core.api.features.AuthFeatureAPI;
|
import pro.gravit.launcher.core.api.features.*;
|
||||||
import pro.gravit.launcher.core.api.features.ProfileFeatureAPI;
|
|
||||||
import pro.gravit.launcher.core.api.features.TextureUploadFeatureAPI;
|
|
||||||
import pro.gravit.launcher.core.api.features.UserFeatureAPI;
|
|
||||||
import pro.gravit.launcher.core.backend.LauncherBackendAPIHolder;
|
import pro.gravit.launcher.core.backend.LauncherBackendAPIHolder;
|
||||||
import pro.gravit.launcher.runtime.backend.LauncherBackendImpl;
|
import pro.gravit.launcher.runtime.backend.LauncherBackendImpl;
|
||||||
import pro.gravit.launcher.runtime.client.*;
|
import pro.gravit.launcher.runtime.client.*;
|
||||||
import pro.gravit.launcher.runtime.client.events.ClientEngineInitPhase;
|
import pro.gravit.launcher.runtime.client.events.ClientEngineInitPhase;
|
||||||
import pro.gravit.launcher.client.events.ClientExitPhase;
|
import pro.gravit.launcher.client.events.ClientExitPhase;
|
||||||
import pro.gravit.launcher.runtime.client.events.ClientPreGuiPhase;
|
import pro.gravit.launcher.runtime.client.events.ClientPreGuiPhase;
|
||||||
import pro.gravit.launcher.runtime.console.GetPublicKeyCommand;
|
|
||||||
import pro.gravit.launcher.runtime.console.ModulesCommand;
|
import pro.gravit.launcher.runtime.console.ModulesCommand;
|
||||||
import pro.gravit.launcher.runtime.console.SignDataCommand;
|
|
||||||
import pro.gravit.launcher.runtime.gui.NoRuntimeProvider;
|
import pro.gravit.launcher.runtime.gui.NoRuntimeProvider;
|
||||||
import pro.gravit.launcher.runtime.gui.RuntimeProvider;
|
import pro.gravit.launcher.runtime.gui.RuntimeProvider;
|
||||||
import pro.gravit.launcher.runtime.managers.ConsoleManager;
|
import pro.gravit.launcher.runtime.managers.ConsoleManager;
|
||||||
|
@ -34,15 +29,8 @@
|
||||||
import pro.gravit.launcher.start.RuntimeModuleManager;
|
import pro.gravit.launcher.start.RuntimeModuleManager;
|
||||||
import pro.gravit.utils.helper.*;
|
import pro.gravit.utils.helper.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.security.KeyPair;
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.security.interfaces.ECPrivateKey;
|
|
||||||
import java.security.interfaces.ECPublicKey;
|
|
||||||
import java.security.spec.InvalidKeySpecException;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
@ -55,8 +43,6 @@ public class LauncherEngine {
|
||||||
// Instance
|
// Instance
|
||||||
private final AtomicBoolean started = new AtomicBoolean(false);
|
private final AtomicBoolean started = new AtomicBoolean(false);
|
||||||
public RuntimeProvider runtimeProvider;
|
public RuntimeProvider runtimeProvider;
|
||||||
public ECPublicKey publicKey;
|
|
||||||
public ECPrivateKey privateKey;
|
|
||||||
public Class<? extends RuntimeProvider> basicRuntimeProvider;
|
public Class<? extends RuntimeProvider> basicRuntimeProvider;
|
||||||
|
|
||||||
private LauncherEngine(boolean clientInstance, Class<? extends RuntimeProvider> basicRuntimeProvider) {
|
private LauncherEngine(boolean clientInstance, Class<? extends RuntimeProvider> basicRuntimeProvider) {
|
||||||
|
@ -183,36 +169,6 @@ public static LauncherEngine newInstance(boolean clientInstance, Class<? extends
|
||||||
return new LauncherEngine(clientInstance, basicRuntimeProvider);
|
return new LauncherEngine(clientInstance, basicRuntimeProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ECPublicKey getClientPublicKey() {
|
|
||||||
return publicKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] sign(byte[] bytes) {
|
|
||||||
return SecurityHelper.sign(bytes, privateKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void readKeys() throws IOException, InvalidKeySpecException {
|
|
||||||
if (privateKey != null || publicKey != null) return;
|
|
||||||
Path dir = DirBridge.dir;
|
|
||||||
Path publicKeyFile = dir.resolve("public.key");
|
|
||||||
Path privateKeyFile = dir.resolve("private.key");
|
|
||||||
if (IOHelper.isFile(publicKeyFile) && IOHelper.isFile(privateKeyFile)) {
|
|
||||||
LogHelper.info("Reading EC keypair");
|
|
||||||
publicKey = SecurityHelper.toPublicECDSAKey(IOHelper.read(publicKeyFile));
|
|
||||||
privateKey = SecurityHelper.toPrivateECDSAKey(IOHelper.read(privateKeyFile));
|
|
||||||
} else {
|
|
||||||
LogHelper.info("Generating EC keypair");
|
|
||||||
KeyPair pair = SecurityHelper.genECDSAKeyPair(new SecureRandom());
|
|
||||||
publicKey = (ECPublicKey) pair.getPublic();
|
|
||||||
privateKey = (ECPrivateKey) pair.getPrivate();
|
|
||||||
|
|
||||||
// Write key pair list
|
|
||||||
LogHelper.info("Writing EC keypair list");
|
|
||||||
IOHelper.write(publicKeyFile, publicKey.getEncoded());
|
|
||||||
IOHelper.write(privateKeyFile, privateKey.getEncoded());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start(String... args) throws Throwable {
|
public void start(String... args) throws Throwable {
|
||||||
//Launcher.modulesManager = new ClientModuleManager(this);
|
//Launcher.modulesManager = new ClientModuleManager(this);
|
||||||
ClientPreGuiPhase event = new ClientPreGuiPhase(null);
|
ClientPreGuiPhase event = new ClientPreGuiPhase(null);
|
||||||
|
@ -258,14 +214,14 @@ public void start(String... args) throws Throwable {
|
||||||
AuthFeatureAPI.class, impl,
|
AuthFeatureAPI.class, impl,
|
||||||
UserFeatureAPI.class, impl,
|
UserFeatureAPI.class, impl,
|
||||||
ProfileFeatureAPI.class, impl,
|
ProfileFeatureAPI.class, impl,
|
||||||
TextureUploadFeatureAPI.class, impl));
|
TextureUploadFeatureAPI.class, impl,
|
||||||
|
HardwareVerificationFeatureAPI.class, impl));
|
||||||
});
|
});
|
||||||
LauncherBackendAPIHolder.setApi(new LauncherBackendImpl());
|
LauncherBackendAPIHolder.setApi(new LauncherBackendImpl());
|
||||||
//
|
//
|
||||||
Objects.requireNonNull(args, "args");
|
Objects.requireNonNull(args, "args");
|
||||||
if (started.getAndSet(true))
|
if (started.getAndSet(true))
|
||||||
throw new IllegalStateException("Launcher has been already started");
|
throw new IllegalStateException("Launcher has been already started");
|
||||||
readKeys();
|
|
||||||
registerCommands();
|
registerCommands();
|
||||||
LauncherEngine.modulesManager.invokeEvent(new ClientEngineInitPhase(this));
|
LauncherEngine.modulesManager.invokeEvent(new ClientEngineInitPhase(this));
|
||||||
runtimeProvider.preLoad();
|
runtimeProvider.preLoad();
|
||||||
|
@ -274,8 +230,6 @@ public void start(String... args) throws Throwable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerCommands() {
|
private void registerCommands() {
|
||||||
ConsoleManager.handler.registerCommand("getpublickey", new GetPublicKeyCommand(this));
|
|
||||||
ConsoleManager.handler.registerCommand("signdata", new SignDataCommand(this));
|
|
||||||
ConsoleManager.handler.registerCommand("modules", new ModulesCommand());
|
ConsoleManager.handler.registerCommand("modules", new ModulesCommand());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
package pro.gravit.launcher.runtime.backend;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.runtime.client.DirBridge;
|
||||||
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
import pro.gravit.utils.helper.SecurityHelper;
|
||||||
|
|
||||||
|
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.spec.InvalidKeySpecException;
|
||||||
|
|
||||||
|
public class ECKeyHolder {
|
||||||
|
public ECPublicKey publicKey;
|
||||||
|
public ECPrivateKey privateKey;
|
||||||
|
|
||||||
|
public ECPublicKey getClientPublicKey() {
|
||||||
|
return publicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] sign(byte[] bytes) {
|
||||||
|
return SecurityHelper.sign(bytes, privateKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readKeys() throws IOException, InvalidKeySpecException {
|
||||||
|
if (privateKey != null || publicKey != null) return;
|
||||||
|
Path dir = DirBridge.dir;
|
||||||
|
Path publicKeyFile = dir.resolve("public.key");
|
||||||
|
Path privateKeyFile = dir.resolve("private.key");
|
||||||
|
if (IOHelper.isFile(publicKeyFile) && IOHelper.isFile(privateKeyFile)) {
|
||||||
|
LogHelper.info("Reading EC keypair");
|
||||||
|
publicKey = SecurityHelper.toPublicECDSAKey(IOHelper.read(publicKeyFile));
|
||||||
|
privateKey = SecurityHelper.toPrivateECDSAKey(IOHelper.read(privateKeyFile));
|
||||||
|
} else {
|
||||||
|
LogHelper.info("Generating EC keypair");
|
||||||
|
KeyPair pair = SecurityHelper.genECDSAKeyPair(new SecureRandom());
|
||||||
|
publicKey = (ECPublicKey) pair.getPublic();
|
||||||
|
privateKey = (ECPrivateKey) pair.getPrivate();
|
||||||
|
|
||||||
|
// Write key pair list
|
||||||
|
LogHelper.info("Writing EC keypair list");
|
||||||
|
IOHelper.write(publicKeyFile, publicKey.getEncoded());
|
||||||
|
IOHelper.write(privateKeyFile, privateKey.getEncoded());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,10 +3,7 @@
|
||||||
import pro.gravit.launcher.base.ClientPermissions;
|
import pro.gravit.launcher.base.ClientPermissions;
|
||||||
import pro.gravit.launcher.base.profiles.ClientProfile;
|
import pro.gravit.launcher.base.profiles.ClientProfile;
|
||||||
import pro.gravit.launcher.core.api.LauncherAPIHolder;
|
import pro.gravit.launcher.core.api.LauncherAPIHolder;
|
||||||
import pro.gravit.launcher.core.api.features.AuthFeatureAPI;
|
import pro.gravit.launcher.core.api.features.*;
|
||||||
import pro.gravit.launcher.core.api.features.CoreFeatureAPI;
|
|
||||||
import pro.gravit.launcher.core.api.features.ProfileFeatureAPI;
|
|
||||||
import pro.gravit.launcher.core.api.features.TextureUploadFeatureAPI;
|
|
||||||
import pro.gravit.launcher.core.api.method.AuthMethod;
|
import pro.gravit.launcher.core.api.method.AuthMethod;
|
||||||
import pro.gravit.launcher.core.api.method.AuthMethodPassword;
|
import pro.gravit.launcher.core.api.method.AuthMethodPassword;
|
||||||
import pro.gravit.launcher.core.api.model.SelfUser;
|
import pro.gravit.launcher.core.api.model.SelfUser;
|
||||||
|
@ -17,14 +14,17 @@
|
||||||
import pro.gravit.launcher.core.backend.exceptions.LauncherBackendException;
|
import pro.gravit.launcher.core.backend.exceptions.LauncherBackendException;
|
||||||
import pro.gravit.launcher.core.backend.extensions.Extension;
|
import pro.gravit.launcher.core.backend.extensions.Extension;
|
||||||
import pro.gravit.launcher.core.backend.extensions.TextureUploadExtension;
|
import pro.gravit.launcher.core.backend.extensions.TextureUploadExtension;
|
||||||
|
import pro.gravit.launcher.runtime.LauncherEngine;
|
||||||
import pro.gravit.launcher.runtime.NewLauncherSettings;
|
import pro.gravit.launcher.runtime.NewLauncherSettings;
|
||||||
import pro.gravit.launcher.runtime.client.DirBridge;
|
import pro.gravit.launcher.runtime.client.DirBridge;
|
||||||
import pro.gravit.launcher.runtime.client.ServerPinger;
|
import pro.gravit.launcher.runtime.client.ServerPinger;
|
||||||
import pro.gravit.launcher.runtime.debug.DebugMain;
|
import pro.gravit.launcher.runtime.debug.DebugMain;
|
||||||
import pro.gravit.launcher.runtime.managers.SettingsManager;
|
import pro.gravit.launcher.runtime.managers.SettingsManager;
|
||||||
|
import pro.gravit.launcher.runtime.utils.HWIDProvider;
|
||||||
import pro.gravit.launcher.runtime.utils.LauncherUpdater;
|
import pro.gravit.launcher.runtime.utils.LauncherUpdater;
|
||||||
import pro.gravit.utils.helper.JavaHelper;
|
import pro.gravit.utils.helper.JavaHelper;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
import pro.gravit.utils.helper.SecurityHelper;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -50,12 +50,15 @@ public class LauncherBackendImpl implements LauncherBackendAPI, TextureUploadExt
|
||||||
private SettingsManager settingsManager;
|
private SettingsManager settingsManager;
|
||||||
private NewLauncherSettings allSettings;
|
private NewLauncherSettings allSettings;
|
||||||
private BackendSettings backendSettings;
|
private BackendSettings backendSettings;
|
||||||
|
// Hardware
|
||||||
|
private volatile ECKeyHolder ecKeyHolder;
|
||||||
// Data
|
// Data
|
||||||
private volatile List<ProfileFeatureAPI.ClientProfile> profiles;
|
private volatile List<ProfileFeatureAPI.ClientProfile> profiles;
|
||||||
private volatile UserPermissions permissions;
|
private volatile UserPermissions permissions;
|
||||||
private volatile SelfUser selfUser;
|
private volatile SelfUser selfUser;
|
||||||
private volatile List<Java> availableJavas;
|
private volatile List<Java> availableJavas;
|
||||||
private volatile CompletableFuture<List<Java>> availableJavasFuture;
|
private volatile CompletableFuture<List<Java>> availableJavasFuture;
|
||||||
|
private volatile CompletableFuture<Void> processHardwareFuture;
|
||||||
private final Map<UUID, CompletableFuture<ServerPingInfo>> pingFutures = new ConcurrentHashMap<>();
|
private final Map<UUID, CompletableFuture<ServerPingInfo>> pingFutures = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -76,6 +79,8 @@ private void doInit() throws Exception {
|
||||||
allSettings = settingsManager.getConfig();
|
allSettings = settingsManager.getConfig();
|
||||||
backendSettings = (BackendSettings) getUserSettings("backend", (k) -> new BackendSettings());
|
backendSettings = (BackendSettings) getUserSettings("backend", (k) -> new BackendSettings());
|
||||||
permissions = new ClientPermissions();
|
permissions = new ClientPermissions();
|
||||||
|
ecKeyHolder = new ECKeyHolder();
|
||||||
|
ecKeyHolder.readKeys();
|
||||||
DirBridge.dirUpdates = DirBridge.defaultUpdatesDir;
|
DirBridge.dirUpdates = DirBridge.defaultUpdatesDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,6 +164,9 @@ private void onAuthorize(SelfUser selfUser) {
|
||||||
this.selfUser = selfUser;
|
this.selfUser = selfUser;
|
||||||
permissions = selfUser.getPermissions();
|
permissions = selfUser.getPermissions();
|
||||||
callback.onAuthorize(selfUser);
|
callback.onAuthorize(selfUser);
|
||||||
|
if(processHardwareFuture == null) {
|
||||||
|
processHardwareFuture = processHardware();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -321,4 +329,33 @@ public CompletableFuture<TextureUploadFeatureAPI.TextureUploadInfo> fetchTexture
|
||||||
public CompletableFuture<Texture> uploadTexture(String name, byte[] bytes, TextureUploadFeatureAPI.UploadSettings settings) {
|
public CompletableFuture<Texture> uploadTexture(String name, byte[] bytes, TextureUploadFeatureAPI.UploadSettings settings) {
|
||||||
return LauncherAPIHolder.get().get(TextureUploadFeatureAPI.class).upload(name, bytes, settings);
|
return LauncherAPIHolder.get().get(TextureUploadFeatureAPI.class).upload(name, bytes, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CompletableFuture<Void> processHardware() {
|
||||||
|
HardwareVerificationFeatureAPI featureAPI = LauncherAPIHolder.get().get(HardwareVerificationFeatureAPI.class);
|
||||||
|
if(featureAPI == null) {
|
||||||
|
return CompletableFuture.completedFuture(null);
|
||||||
|
}
|
||||||
|
return featureAPI.getSecurityInfo().thenCompose((response) -> {
|
||||||
|
if(!response.isRequired()) {
|
||||||
|
return CompletableFuture.completedFuture(null);
|
||||||
|
}
|
||||||
|
byte[] signature = SecurityHelper.sign(response.getSignData(), ecKeyHolder.privateKey);
|
||||||
|
return featureAPI.privateKeyVerification(ecKeyHolder.publicKey, signature);
|
||||||
|
}).thenCompose((response) -> {
|
||||||
|
switch (response.getHardwareCollectLevel()) {
|
||||||
|
case NONE -> {
|
||||||
|
return featureAPI.sendHardwareInfo(null, null);
|
||||||
|
}
|
||||||
|
case ONLY_STATISTIC -> {
|
||||||
|
HWIDProvider hwidProvider = new HWIDProvider();
|
||||||
|
return featureAPI.sendHardwareInfo(hwidProvider.getStatisticData(), null);
|
||||||
|
}
|
||||||
|
case ALL -> {
|
||||||
|
HWIDProvider hwidProvider = new HWIDProvider();
|
||||||
|
return featureAPI.sendHardwareInfo(hwidProvider.getStatisticData(), hwidProvider.getIdentifyData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CompletableFuture.failedFuture(new UnsupportedOperationException());
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
package pro.gravit.launcher.runtime.console;
|
|
||||||
|
|
||||||
import pro.gravit.launcher.runtime.LauncherEngine;
|
|
||||||
import pro.gravit.utils.command.Command;
|
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
|
||||||
|
|
||||||
import java.util.Base64;
|
|
||||||
|
|
||||||
public class GetPublicKeyCommand extends Command {
|
|
||||||
private final LauncherEngine engine;
|
|
||||||
|
|
||||||
public GetPublicKeyCommand(LauncherEngine engine) {
|
|
||||||
this.engine = engine;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getArgsDescription() {
|
|
||||||
return "[]";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUsageDescription() {
|
|
||||||
return "print public key in base64 format";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void invoke(String... args) {
|
|
||||||
LogHelper.info("PublicKey: %s", Base64.getEncoder().encodeToString(engine.getClientPublicKey().getEncoded()));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
package pro.gravit.launcher.runtime.console;
|
|
||||||
|
|
||||||
import pro.gravit.launcher.runtime.LauncherEngine;
|
|
||||||
import pro.gravit.utils.command.Command;
|
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
|
||||||
|
|
||||||
import java.util.Base64;
|
|
||||||
|
|
||||||
public class SignDataCommand extends Command {
|
|
||||||
private final LauncherEngine engine;
|
|
||||||
|
|
||||||
public SignDataCommand(LauncherEngine engine) {
|
|
||||||
this.engine = engine;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getArgsDescription() {
|
|
||||||
return "[base64 data]";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUsageDescription() {
|
|
||||||
return "sign any data";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void invoke(String... args) throws Exception {
|
|
||||||
verifyArgs(args, 1);
|
|
||||||
byte[] data = Base64.getDecoder().decode(args[0]);
|
|
||||||
byte[] signature = engine.sign(data);
|
|
||||||
String base64 = Base64.getEncoder().encodeToString(signature);
|
|
||||||
LogHelper.info("Signature: %s", base64);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,6 +4,8 @@
|
||||||
import oshi.hardware.*;
|
import oshi.hardware.*;
|
||||||
import oshi.software.os.OperatingSystem;
|
import oshi.software.os.OperatingSystem;
|
||||||
import pro.gravit.launcher.base.request.secure.HardwareReportRequest;
|
import pro.gravit.launcher.base.request.secure.HardwareReportRequest;
|
||||||
|
import pro.gravit.launcher.core.api.features.HardwareVerificationFeatureAPI;
|
||||||
|
import pro.gravit.utils.helper.JVMHelper;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -104,6 +106,27 @@ public String getBaseboardSerialNumber() {
|
||||||
return hardware.getComputerSystem().getBaseboard().getSerialNumber();
|
return hardware.getComputerSystem().getBaseboard().getSerialNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HardwareVerificationFeatureAPI.HardwareStatisticData getStatisticData() {
|
||||||
|
return new HardwareVerificationFeatureAPI.HardwareStatisticData(
|
||||||
|
JVMHelper.ARCH.toHardwareFeatureArch(JVMHelper.ARCH_TYPE),
|
||||||
|
JVMHelper.OS.toHardwareFeatureOs(JVMHelper.OS_TYPE),
|
||||||
|
getTotalMemory(),
|
||||||
|
getProcessorLogicalCount(),
|
||||||
|
getProcessorPhysicalCount(),
|
||||||
|
getProcessorMaxFreq(),
|
||||||
|
isBattery(),
|
||||||
|
getGraphicCardName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HardwareVerificationFeatureAPI.HardwareIdentifyData getIdentifyData() {
|
||||||
|
return new HardwareVerificationFeatureAPI.HardwareIdentifyData(
|
||||||
|
getBaseboardSerialNumber(),
|
||||||
|
getHWDiskID(),
|
||||||
|
getDisplayID()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public HardwareReportRequest.HardwareInfo getHardwareInfo(boolean needSerial) {
|
public HardwareReportRequest.HardwareInfo getHardwareInfo(boolean needSerial) {
|
||||||
HardwareReportRequest.HardwareInfo info = new HardwareReportRequest.HardwareInfo();
|
HardwareReportRequest.HardwareInfo info = new HardwareReportRequest.HardwareInfo();
|
||||||
info.bitness = getBitness();
|
info.bitness = getBitness();
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package pro.gravit.launcher.base.events.request;
|
package pro.gravit.launcher.base.events.request;
|
||||||
|
|
||||||
import pro.gravit.launcher.base.events.RequestEvent;
|
import pro.gravit.launcher.base.events.RequestEvent;
|
||||||
|
import pro.gravit.launcher.core.api.features.HardwareVerificationFeatureAPI;
|
||||||
|
|
||||||
public class GetSecureLevelInfoRequestEvent extends RequestEvent {
|
public class GetSecureLevelInfoRequestEvent extends RequestEvent implements HardwareVerificationFeatureAPI.SecurityLevelInfo {
|
||||||
public final byte[] verifySecureKey;
|
public final byte[] verifySecureKey;
|
||||||
public boolean enabled;
|
public boolean enabled;
|
||||||
|
|
||||||
|
@ -19,4 +20,14 @@ public GetSecureLevelInfoRequestEvent(byte[] verifySecureKey, boolean enabled) {
|
||||||
public String getType() {
|
public String getType() {
|
||||||
return "getSecureLevelInfo";
|
return "getSecureLevelInfo";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRequired() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] getSignData() {
|
||||||
|
return verifySecureKey;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
|
|
||||||
import pro.gravit.launcher.base.events.ExtendedTokenRequestEvent;
|
import pro.gravit.launcher.base.events.ExtendedTokenRequestEvent;
|
||||||
import pro.gravit.launcher.base.events.RequestEvent;
|
import pro.gravit.launcher.base.events.RequestEvent;
|
||||||
|
import pro.gravit.launcher.core.api.features.HardwareVerificationFeatureAPI;
|
||||||
|
|
||||||
public class VerifySecureLevelKeyRequestEvent extends RequestEvent implements ExtendedTokenRequestEvent {
|
public class VerifySecureLevelKeyRequestEvent extends RequestEvent implements ExtendedTokenRequestEvent, HardwareVerificationFeatureAPI.SecurityLevelVerification {
|
||||||
public boolean needHardwareInfo;
|
public boolean needHardwareInfo;
|
||||||
public boolean onlyStatisticInfo;
|
public boolean onlyStatisticInfo;
|
||||||
public String extendedToken;
|
public String extendedToken;
|
||||||
|
@ -42,4 +43,17 @@ public String getExtendedToken() {
|
||||||
public long getExtendedTokenExpire() {
|
public long getExtendedTokenExpire() {
|
||||||
return expire;
|
return expire;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HardwareCollectLevel getHardwareCollectLevel() {
|
||||||
|
if(needHardwareInfo) {
|
||||||
|
if(onlyStatisticInfo) {
|
||||||
|
return HardwareCollectLevel.ONLY_STATISTIC;
|
||||||
|
} else {
|
||||||
|
return HardwareCollectLevel.ALL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return HardwareCollectLevel.NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
package pro.gravit.launcher.base.request;
|
package pro.gravit.launcher.base.request;
|
||||||
|
|
||||||
import pro.gravit.launcher.base.Launcher;
|
import pro.gravit.launcher.base.Launcher;
|
||||||
|
import pro.gravit.launcher.base.events.request.VerifySecureLevelKeyRequestEvent;
|
||||||
import pro.gravit.launcher.base.profiles.ClientProfile;
|
import pro.gravit.launcher.base.profiles.ClientProfile;
|
||||||
import pro.gravit.launcher.base.request.auth.*;
|
import pro.gravit.launcher.base.request.auth.*;
|
||||||
import pro.gravit.launcher.base.request.auth.password.*;
|
import pro.gravit.launcher.base.request.auth.password.*;
|
||||||
import pro.gravit.launcher.base.request.cabinet.AssetUploadInfoRequest;
|
import pro.gravit.launcher.base.request.cabinet.AssetUploadInfoRequest;
|
||||||
import pro.gravit.launcher.base.request.cabinet.GetAssetUploadUrl;
|
import pro.gravit.launcher.base.request.cabinet.GetAssetUploadUrl;
|
||||||
|
import pro.gravit.launcher.base.request.secure.GetSecureLevelInfoRequest;
|
||||||
|
import pro.gravit.launcher.base.request.secure.HardwareReportRequest;
|
||||||
|
import pro.gravit.launcher.base.request.secure.VerifySecureLevelKeyRequest;
|
||||||
import pro.gravit.launcher.base.request.update.ProfilesRequest;
|
import pro.gravit.launcher.base.request.update.ProfilesRequest;
|
||||||
import pro.gravit.launcher.base.request.update.UpdateRequest;
|
import pro.gravit.launcher.base.request.update.UpdateRequest;
|
||||||
import pro.gravit.launcher.base.request.uuid.ProfileByUUIDRequest;
|
import pro.gravit.launcher.base.request.uuid.ProfileByUUIDRequest;
|
||||||
import pro.gravit.launcher.base.request.uuid.ProfileByUsernameRequest;
|
import pro.gravit.launcher.base.request.uuid.ProfileByUsernameRequest;
|
||||||
import pro.gravit.launcher.core.LauncherNetworkAPI;
|
import pro.gravit.launcher.core.LauncherNetworkAPI;
|
||||||
import pro.gravit.launcher.core.api.features.AuthFeatureAPI;
|
import pro.gravit.launcher.core.api.features.*;
|
||||||
import pro.gravit.launcher.core.api.features.TextureUploadFeatureAPI;
|
|
||||||
import pro.gravit.launcher.core.api.features.UserFeatureAPI;
|
|
||||||
import pro.gravit.launcher.core.api.features.ProfileFeatureAPI;
|
|
||||||
import pro.gravit.launcher.core.api.method.AuthMethodPassword;
|
import pro.gravit.launcher.core.api.method.AuthMethodPassword;
|
||||||
import pro.gravit.launcher.core.api.method.password.AuthChainPassword;
|
import pro.gravit.launcher.core.api.method.password.AuthChainPassword;
|
||||||
import pro.gravit.launcher.core.api.method.password.AuthOAuthPassword;
|
import pro.gravit.launcher.core.api.method.password.AuthOAuthPassword;
|
||||||
|
@ -32,13 +33,14 @@
|
||||||
import java.net.http.HttpRequest;
|
import java.net.http.HttpRequest;
|
||||||
import java.net.http.HttpResponse;
|
import java.net.http.HttpResponse;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.PublicKey;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public class RequestFeatureAPIImpl implements AuthFeatureAPI, UserFeatureAPI, ProfileFeatureAPI, TextureUploadFeatureAPI {
|
public class RequestFeatureAPIImpl implements AuthFeatureAPI, UserFeatureAPI, ProfileFeatureAPI, TextureUploadFeatureAPI, HardwareVerificationFeatureAPI {
|
||||||
private final RequestService request;
|
private final RequestService request;
|
||||||
private final String authId;
|
private final String authId;
|
||||||
private final HttpClient client = HttpClient.newBuilder().build();
|
private final HttpClient client = HttpClient.newBuilder().build();
|
||||||
|
@ -249,6 +251,40 @@ public CompletableFuture<Texture> upload(String name, byte[] bytes, UploadSettin
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<SecurityLevelInfo> getSecurityInfo() {
|
||||||
|
return request.request(new GetSecureLevelInfoRequest()).thenApply(response -> response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<SecurityLevelVerification> privateKeyVerification(PublicKey publicKey, byte[] signature) {
|
||||||
|
return request.request(new VerifySecureLevelKeyRequest(publicKey.getEncoded(), signature)).thenApply(response -> response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Void> sendHardwareInfo(HardwareStatisticData statisticData, HardwareIdentifyData identifyData) {
|
||||||
|
if(statisticData == null && identifyData == null) { // Hardware info token special
|
||||||
|
return request.request(new HardwareReportRequest()).thenApply(response -> null);
|
||||||
|
} else {
|
||||||
|
var hardwareInfo = new HardwareReportRequest.HardwareInfo();
|
||||||
|
if(statisticData != null) {
|
||||||
|
hardwareInfo.bitness = statisticData.arch() == Arch.X86 || statisticData.arch() == Arch.ARM32 ? 32 : 64;
|
||||||
|
hardwareInfo.totalMemory = statisticData.totalPhysicalMemory();
|
||||||
|
hardwareInfo.logicalProcessors = statisticData.logicalProcessors();
|
||||||
|
hardwareInfo.physicalProcessors = statisticData.physicalProcessors();
|
||||||
|
hardwareInfo.processorMaxFreq = statisticData.processorMaxFreq();
|
||||||
|
hardwareInfo.battery = statisticData.battery();
|
||||||
|
hardwareInfo.graphicCard = statisticData.graphicCard();
|
||||||
|
}
|
||||||
|
if(identifyData != null) {
|
||||||
|
hardwareInfo.hwDiskId = identifyData.persistentStorageId();
|
||||||
|
hardwareInfo.displayId = identifyData.edid();
|
||||||
|
hardwareInfo.baseboardSerialNumber = identifyData.baseboardSerialNumber();
|
||||||
|
}
|
||||||
|
return request.request(new HardwareReportRequest(hardwareInfo)).thenApply(response -> null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public record UpdateInfoData(HashedDir hdir, String url) implements ProfileFeatureAPI.UpdateInfo {
|
public record UpdateInfoData(HashedDir hdir, String url) implements ProfileFeatureAPI.UpdateInfo {
|
||||||
@Override
|
@Override
|
||||||
public HashedDir getHashedDir() {
|
public HashedDir getHashedDir() {
|
||||||
|
|
|
@ -8,6 +8,13 @@
|
||||||
public class HardwareReportRequest extends Request<HardwareReportRequestEvent> {
|
public class HardwareReportRequest extends Request<HardwareReportRequestEvent> {
|
||||||
public HardwareInfo hardware;
|
public HardwareInfo hardware;
|
||||||
|
|
||||||
|
public HardwareReportRequest() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public HardwareReportRequest(HardwareInfo hardware) {
|
||||||
|
this.hardware = hardware;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getType() {
|
public String getType() {
|
||||||
return "hardwareReport";
|
return "hardwareReport";
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
package pro.gravit.launcher.core.api.features;
|
||||||
|
|
||||||
|
import pro.gravit.utils.helper.JVMHelper;
|
||||||
|
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
public interface HardwareVerificationFeatureAPI extends FeatureAPI {
|
||||||
|
CompletableFuture<SecurityLevelInfo> getSecurityInfo();
|
||||||
|
CompletableFuture<SecurityLevelVerification> privateKeyVerification(PublicKey publicKey, byte[] signature);
|
||||||
|
CompletableFuture<Void> sendHardwareInfo(HardwareStatisticData statisticData, HardwareIdentifyData identifyData);
|
||||||
|
|
||||||
|
|
||||||
|
interface SecurityLevelInfo {
|
||||||
|
boolean isRequired();
|
||||||
|
byte[] getSignData();
|
||||||
|
}
|
||||||
|
interface SecurityLevelVerification {
|
||||||
|
HardwareCollectLevel getHardwareCollectLevel();
|
||||||
|
|
||||||
|
enum HardwareCollectLevel {
|
||||||
|
NONE, ONLY_STATISTIC, ALL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record HardwareStatisticData(Arch arch, Os os, long totalPhysicalMemory,
|
||||||
|
int logicalProcessors, int physicalProcessors,
|
||||||
|
long processorMaxFreq, boolean battery,
|
||||||
|
String graphicCard) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
record HardwareIdentifyData(String baseboardSerialNumber, String persistentStorageId,
|
||||||
|
byte[] edid) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Arch {
|
||||||
|
X86("x86"), X86_64("x86-64"), ARM64("arm64"), ARM32("arm32");
|
||||||
|
|
||||||
|
public final String name;
|
||||||
|
|
||||||
|
Arch(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Os {
|
||||||
|
WINDOWS("windows"), LINUX("linux"), MACOS("macos");
|
||||||
|
|
||||||
|
public final String name;
|
||||||
|
|
||||||
|
Os(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
package pro.gravit.utils.helper;
|
package pro.gravit.utils.helper;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.core.api.features.HardwareVerificationFeatureAPI;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
import java.lang.management.ManagementFactory;
|
import java.lang.management.ManagementFactory;
|
||||||
import java.lang.management.OperatingSystemMXBean;
|
import java.lang.management.OperatingSystemMXBean;
|
||||||
|
@ -56,7 +58,7 @@ public static int getBuild() {
|
||||||
return Runtime.version().update();
|
return Runtime.version().update();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getNativeExtension(JVMHelper.OS OS_TYPE) {
|
public static String getNativeExtension(OS OS_TYPE) {
|
||||||
return switch (OS_TYPE) {
|
return switch (OS_TYPE) {
|
||||||
case MUSTDIE -> ".dll";
|
case MUSTDIE -> ".dll";
|
||||||
case LINUX -> ".so";
|
case LINUX -> ".so";
|
||||||
|
@ -64,7 +66,7 @@ public static String getNativeExtension(JVMHelper.OS OS_TYPE) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getNativePrefix(JVMHelper.OS OS_TYPE) {
|
public static String getNativePrefix(OS OS_TYPE) {
|
||||||
return switch (OS_TYPE) {
|
return switch (OS_TYPE) {
|
||||||
case LINUX, MACOSX -> "lib";
|
case LINUX, MACOSX -> "lib";
|
||||||
default -> "";
|
default -> "";
|
||||||
|
@ -124,6 +126,15 @@ public enum ARCH {
|
||||||
|
|
||||||
public final String name;
|
public final String name;
|
||||||
|
|
||||||
|
public static HardwareVerificationFeatureAPI.Arch toHardwareFeatureArch(ARCH arch) {
|
||||||
|
return switch (arch) {
|
||||||
|
case X86 -> HardwareVerificationFeatureAPI.Arch.X86;
|
||||||
|
case X86_64 -> HardwareVerificationFeatureAPI.Arch.X86_64;
|
||||||
|
case ARM64 -> HardwareVerificationFeatureAPI.Arch.ARM64;
|
||||||
|
case ARM32 -> HardwareVerificationFeatureAPI.Arch.ARM32;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
ARCH(String name) {
|
ARCH(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
@ -138,6 +149,14 @@ public enum OS {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static HardwareVerificationFeatureAPI.Os toHardwareFeatureOs(OS os) {
|
||||||
|
return switch (os) {
|
||||||
|
case MUSTDIE -> HardwareVerificationFeatureAPI.Os.WINDOWS;
|
||||||
|
case LINUX -> HardwareVerificationFeatureAPI.Os.LINUX;
|
||||||
|
case MACOSX -> HardwareVerificationFeatureAPI.Os.MACOS;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public static OS byName(String name) {
|
public static OS byName(String name) {
|
||||||
if (name.startsWith("Windows"))
|
if (name.startsWith("Windows"))
|
||||||
return MUSTDIE;
|
return MUSTDIE;
|
||||||
|
|
Loading…
Reference in a new issue