为了使基础变得更简单,我正在使用Eclipse编写代码并创建我的可执行jar文件。
一些背景研究:
我知道您可以反编译jar文件并查看源代码。实际上,那里有免费的程序,例如 JD GUI ,可以轻松地反编译jar文件并显示其所有内容。尤其是如果您要分发Java程序时,这是一个问题。
当我了解到这一点后,我立即开始寻找解决方案,但找不到直接的答案。
问题:
我的问题是,如何加密jar文件,或至少加密类文件以使其不可读如果您要反编译的话?
我一直看到的一种解决方案是可以对代码进行混淆,但是问题是您的代码仍然必须能够运行,因此可以对混淆进行一些逆向工程努力。我能想到的唯一其他解决方案是拥有两个单独的jar文件,以便其中一个jar文件被加密,并需要另一个jar文件对其进行解密。现在,在您说“他们可以反编译另一个jar并将其用于解密第一个jar之前”。我的想法是使用用于解密第一个jar的密码。从理论上讲,用户可以知道确切的解密方法,但是如果没有密码(密码),它将完全无用。
我的问题
我将如何实施?我问我如何运行一个jar文件,用用户指定的密码对另一个jar进行加密/解密?
随意提供示例代码,我在寻找我能得到的任何帮助。
谢谢!
答案 0 :(得分:2)
假设您有一个JAR文件,其中某些类在编译后已加密。
假设您要加密并执行一个名为SecureMain
的加密类:
public class SecureMain implements Runnable {
@Override
public void run() {
System.out.println("Running...");
}
}
给出以下JAR文件结构:
org
`---stackoveflow
`---example
|---EncryptedClassLoader.class
|---Main.class
`---SecureMain.enc
文件扩展名为enc
的文件使用某些密钥进行加密。
EncryptedClassLoader
可用于在加载类文件之前对其进行解密:
public class EncryptedClassLoader extends ClassLoader {
private final SecretKeySpec key;
public EncryptedClassLoader(SecretKeySpec key) {
this.key = key;
}
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
String[] segments = name.split("\\.");
String filePath = String.join("/", segments) + ".enc";
byte[] bytes = decryptResource(filePath);
return defineClass(name, bytes, 0, bytes.length);
} catch (Exception e) {
throw new ClassNotFoundException("Unable to load class: " + name, e);
}
}
private byte[] decryptResource(String filePath) throws Exception {
File file = new File(getResource(filePath).getFile());
byte[] bytes = Files.readAllBytes(file.toPath());
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key);
return cipher.doFinal(bytes);
}
}
然后可以实现Main
类,以从命令行参数加载密钥,然后加载并执行加密的SecureMain
类:
public class Main {
public static void main(String[] args) throws Exception {
byte[] bytes = Base64.getDecoder().decode(args[0]);
SecretKeySpec key = new SecretKeySpec(bytes, "AES");
ClassLoader loader = new EncryptedClassLoader(key);
Class<?> cls = loader.loadClass("com.stackoverflow.example.SecureMain");
Runnable main = (Runnable) cls.newInstance();
main.run();
}
}
最后,应该使用作为参数传递的密钥来执行JAR。
java -jar myjar.jar <base64 encoded key>