mirror of
https://github.com/GravitLauncher/Launcher
synced 2025-06-28 12:08:09 +03:00
[FEATURE] Support Runtime encrypt and themes part 1
This commit is contained in:
parent
37546e8a5a
commit
324de7226d
3 changed files with 133 additions and 0 deletions
|
@ -0,0 +1,50 @@
|
||||||
|
package pro.gravit.launcher.runtime.backend;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.base.Launcher;
|
||||||
|
import pro.gravit.launcher.base.vfs.Vfs;
|
||||||
|
import pro.gravit.launcher.base.vfs.VfsFile;
|
||||||
|
import pro.gravit.utils.helper.SecurityHelper;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.CipherInputStream;
|
||||||
|
import javax.crypto.NoSuchPaddingException;
|
||||||
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
|
public class EncryptedVfsFile extends VfsFile {
|
||||||
|
private VfsFile parent;
|
||||||
|
private final String alg;
|
||||||
|
private final SecretKeySpec sKeySpec;
|
||||||
|
private final IvParameterSpec iKeySpec;
|
||||||
|
|
||||||
|
public EncryptedVfsFile(VfsFile parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
this.alg = "AES/CBC/PKCS5Padding";
|
||||||
|
try {
|
||||||
|
byte[] compat = SecurityHelper.getAESKey(Launcher.getConfig().runtimeEncryptKey.getBytes(StandardCharsets.UTF_8));
|
||||||
|
sKeySpec = new SecretKeySpec(compat, "AES");
|
||||||
|
iKeySpec = new IvParameterSpec("8u3d90ikr7o67lsq".getBytes());
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new SecurityException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getInputStream() {
|
||||||
|
Cipher cipher;
|
||||||
|
try {
|
||||||
|
cipher = Cipher.getInstance(alg);
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, sKeySpec, iKeySpec);
|
||||||
|
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException |
|
||||||
|
InvalidAlgorithmParameterException e) {
|
||||||
|
throw new SecurityException(e);
|
||||||
|
}
|
||||||
|
return new BufferedInputStream(new CipherInputStream(parent.getInputStream(), cipher));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,12 @@
|
||||||
package pro.gravit.launcher.runtime.backend;
|
package pro.gravit.launcher.runtime.backend;
|
||||||
|
|
||||||
import pro.gravit.launcher.base.ClientPermissions;
|
import pro.gravit.launcher.base.ClientPermissions;
|
||||||
|
import pro.gravit.launcher.base.Launcher;
|
||||||
import pro.gravit.launcher.base.profiles.ClientProfile;
|
import pro.gravit.launcher.base.profiles.ClientProfile;
|
||||||
|
import pro.gravit.launcher.base.vfs.Vfs;
|
||||||
|
import pro.gravit.launcher.base.vfs.directory.FileVfsDirectory;
|
||||||
|
import pro.gravit.launcher.base.vfs.file.CachedVfsFile;
|
||||||
|
import pro.gravit.launcher.base.vfs.file.UrlVfsFile;
|
||||||
import pro.gravit.launcher.core.api.LauncherAPIHolder;
|
import pro.gravit.launcher.core.api.LauncherAPIHolder;
|
||||||
import pro.gravit.launcher.core.api.features.*;
|
import pro.gravit.launcher.core.api.features.*;
|
||||||
import pro.gravit.launcher.core.api.method.AuthMethod;
|
import pro.gravit.launcher.core.api.method.AuthMethod;
|
||||||
|
@ -22,12 +27,15 @@
|
||||||
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.HWIDProvider;
|
||||||
import pro.gravit.launcher.runtime.utils.LauncherUpdater;
|
import pro.gravit.launcher.runtime.utils.LauncherUpdater;
|
||||||
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
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 pro.gravit.utils.helper.SecurityHelper;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.nio.file.NoSuchFileException;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
|
@ -370,4 +378,34 @@ public CompletableFuture<Void> processHardware() {
|
||||||
return CompletableFuture.failedFuture(new UnsupportedOperationException());
|
return CompletableFuture.failedFuture(new UnsupportedOperationException());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Path initVfsDirectory() {
|
||||||
|
Path defaultPath = Path.of("runtime");
|
||||||
|
if(isTestMode()) {
|
||||||
|
Vfs.get().put(defaultPath, new FileVfsDirectory(defaultPath));
|
||||||
|
} else {
|
||||||
|
var encryptKey = Launcher.getConfig().runtimeEncryptKey;
|
||||||
|
if(encryptKey == null) {
|
||||||
|
for(var e : Launcher.getConfig().runtime.entrySet()) {
|
||||||
|
var realPath = e.getKey();
|
||||||
|
var encodedName = "runtime/" + realPath;
|
||||||
|
try {
|
||||||
|
Vfs.get().put(defaultPath.resolve(realPath), new UrlVfsFile(IOHelper.getResourceURL(encodedName)));
|
||||||
|
} catch (NoSuchFileException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(var e : Launcher.getConfig().runtime.entrySet()) {
|
||||||
|
var realPath = e.getKey();
|
||||||
|
var hash = e.getValue();
|
||||||
|
var encodedName = "runtime/" + SecurityHelper.toHex(hash);
|
||||||
|
try {
|
||||||
|
Vfs.get().put(defaultPath.resolve(realPath), new CachedVfsFile(new EncryptedVfsFile(new UrlVfsFile(IOHelper.getResourceURL(encodedName)))));
|
||||||
|
} catch (NoSuchFileException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultPath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package pro.gravit.launcher.base.vfs.file;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.base.vfs.VfsFile;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.lang.ref.SoftReference;
|
||||||
|
|
||||||
|
public class CachedVfsFile extends VfsFile {
|
||||||
|
private final VfsFile delegate;
|
||||||
|
private volatile SoftReference<byte[]> cache;
|
||||||
|
|
||||||
|
public CachedVfsFile(VfsFile delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized InputStream tryCache() {
|
||||||
|
try {
|
||||||
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
|
try(InputStream input = delegate.getInputStream()) {
|
||||||
|
input.transferTo(output);
|
||||||
|
}
|
||||||
|
byte[] bytes = output.toByteArray();
|
||||||
|
cache = new SoftReference<>(bytes);
|
||||||
|
return new ByteArrayInputStream(bytes);
|
||||||
|
} catch (OutOfMemoryError | IOException ignored) {
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getInputStream() {
|
||||||
|
var cachedBytes = cache == null ? null : cache.get();
|
||||||
|
if(cachedBytes != null) {
|
||||||
|
return new ByteArrayInputStream(cachedBytes);
|
||||||
|
}
|
||||||
|
var cached = tryCache();
|
||||||
|
if(cached != null) {
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
return delegate.getInputStream();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue