加密可执行jar

时间:2018-12-05 00:43:06

标签: java security encryption

为了使基础变得更简单,我正在使用Eclipse编写代码并创建我的可执行jar文件。

一些背景研究:
我知道您可以反编译jar文件并查看源代码。实际上,那里有免费的程序,例如 JD GUI ,可以轻松地反编译jar文件并显示其所有内容。尤其是如果您要分发Java程序时,这是一个问题。
当我了解到这一点后,我立即开始寻找解决方案,但找不到直接的答案。

问题:
我的问题是,如何加密jar文件,或至少加密类文件以使其不可读如果您要反编译的话?
我一直看到的一种解决方案是可以对代码进行混淆,但是问题是您的代码仍然必须能够运行,因此可以对混淆进行一些逆向工程努力。我能想到的唯一其他解决方案是拥有两个单独的jar文件,以便其中一个jar文件被加密,并需要另一个jar文件对其进行解密。现在,在您说“他们可以反编译另一个jar并将其用于解密第一个jar之前”。我的想法是使用用于解密第一个jar的密码。从理论上讲,用户可以知道确切的解密方法,但是如果没有密码(密码),它将完全无用。

我的问题
我将如何实施?我问我如何运行一个jar文件,用用户指定的密码对另一个jar进行加密/解密?
随意提供示例代码,我在寻找我能得到的任何帮助。

谢谢!

1 个答案:

答案 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>