免责声明:本人不是安全专家。
听起来像个糟糕的主意:您让某人使用您提供的“隐藏”密钥对内容进行加密。我认为这样做无法保证安全性。
也许非对称加密可以解决问题:
我不确定,但我相信客户实际上可以使用您提供的公钥加密许可证密钥。然后您可以使用自己的私钥解密它,再重新加密。
您可以为每个客户保留单独的公钥/私钥对,以确保您从正确的客户那里收到内容 - 现在,您要负责这些密钥...
@jatanp: 或者更好的办法是,他们可以反编译、删除授权代码并重新编译。对于Java而言,我认为没有一种适当的、防黑客攻击的解决方案。即使是一个邪恶的小型加密狗也无法防止这种情况在Java中发生。
我的业务经理担心这个问题,我也有同感。但是,我们将应用程序销售给遵守许可条件的大型企业,通常由于会计师和律师的存在,这是一个相对安全的环境。如果您的许可证书编写正确,反编译本身可能是非法的。
所以,我必须问一下,您是否真的需要像您为应用程序寻求的那样坚固的保护?您的客户群是什么样子的?(企业?还是青少年游戏玩家群体,这将更成为一个问题?)
您可以毫不担心地使用字节码加密。
事实上,上述引用的论文“破解Java字节码加密”存在逻辑谬误。该论文的主要观点是,在运行之前必须对所有类进行解密并传递给ClassLoader.defineClass(...)
方法。但这是不正确的。
这里错失的假设是“只要它们在真实的或标准的Java运行时环境中运行”。保护的Java应用程序不仅没有义务启动这些类,而且甚至不需要解密和传递它们给ClassLoader
。换句话说,如果您使用标准JRE,则无法拦截defineClass(...)
方法,因为标准Java没有用于此目的的API。如果您使用修改过的带有修补过的ClassLoader
或其他任何“黑客技巧”的JRE,则无法这样做,因为受保护的Java应用程序根本无法工作,因此您将无法拦截任何东西。无论使用哪种“修补程序查找器”或黑客使用哪种技巧,这些技术细节都是完全不同的故事。
问:如果我加密我的.class文件并使用自定义类加载器动态加载和解密它们,这样能防止反编译吗?
答:防止Java字节码反编译的问题几乎和语言本身一样古老。尽管市场上有许多混淆工具可用,但新手Java程序员仍然想出了新的聪明方法来保护他们的知识产权。在这个Java Q&A中,我揭示了一些在讨论论坛中经常被重复提到的想法的谬误。
Java .class文件可以轻松地重构为与原始文件非常相似的Java源代码,这种极易发生的情况与Java字节码设计目标和权衡有很大关系。Java字节码除了紧凑、平台无关、网络移动性和易于被字节码解释器和JIT(即时)/HotSpot动态编译器分析之外,还有其他方面的设计目标。可以说,编译后的.class文件表达了程序员的意图,因此比原始源代码更容易分析。
有几件事情可以做,即使不能完全防止反编译,至少可以使其更加困难。例如,作为后编译步骤,您可以对 .class 数据进行处理,使字节码在反编译时更难读取或更难反编译成有效的 Java 代码(或两者兼而有之)。像执行极端方法名称重载这样的技术对前者非常有效,而操纵控制流以创建无法通过 Java 语法表示的控制结构对后者非常有效。更成功的商业混淆器使用这些和其他技术的混合。
不幸的是,这两种方法都必须实际更改 JVM 将运行的代码,许多用户担心(理所当然)这种转换可能会向他们的应用程序添加新的错误。此外,方法和字段重命名可能会导致反射调用停止工作。更改实际的类和包名称可能会破坏其他几个 Java API(JNDI(Java 命名和目录接口),URL 提供程序等)。除了更改名称之外,如果类字节码偏移量与源行号之间的关联发生变化,则恢复原始异常堆栈跟踪可能会变得困难。
然后还有一种选择,就是混淆原始的 Java 源代码。但从根本上讲,这会导致类似的问题。加密而不是混淆?
也许上面的内容让你想到了:“如果我不是操作字节码,而是在编译后加密所有的类,并在JVM内部动态解密它们(可以使用自定义类加载器完成),那么JVM将执行我的原始字节码,但没有任何反编译或逆向工程可言,对吗?”