文章目录
- 前言
- 常见加密方案对比
- XJar
- ProGuard
- ClassFinal
- ClassFinal实战
- 纯命令方式
- maven插件方式
- 写在最后
前言
相信不少的同学开发的软件都是用户商业化,对于这些商业运营的项目很多都会直接部署在客户方,这样就可能会导致项目源码泄露。当然,作为Java语言的搬砖人打的jar包更是如此,可以直接通过GUI反编译轻而易举拿到源码。那么,有没有对我们class文件加密和代码混淆的实战方案呢?答案当然是有的,今天我们就分享一下常规的加密方案。
常见加密方案对比
XJar
Spring Boot JAR 安全加密运行工具,同时支持的原生JAR。
基于对JAR包内资源的加密以及拓展ClassLoader来构建的一套程序加密启动,动态解密运行的方案,避免源码泄露或反编译
功能特性:
无需侵入代码,只需要把编译好的JAR包通过工具加密即可。
完全内存解密,杜绝源码以及字节码泄露或反编译。
支持所有JDK内置加解密算法。
可选择需要加解密的字节码或其他资源文件,避免计算资源浪费。
运行环境:
新版XJar只支持go启动器模式启动加密后的jar包 , 加密后需要go环境生成go启动器 . 运行时不需要go环境。
加密原理:
对jar的字节码加密 , 启动jar包时调用自定义的类加载器, 重写findClass方法,拿到字节流后,先解密再调Classloader的defineClass方法,初始化成Class对象。
加密结果:
加密后的Class不能反编译。
ProGuard
ProGuard 是一个免费的 Java 类文件的压缩,优化,混淆器。它删除没有用的类,字段,方法与属性。使字节码最大程度地优化,使用简短且无意义的名字来重命名类、字段和方法 。
功能特性:
1、压缩(shrink) 移除未使用的类、方法、字段等;
2、优化(optimize)优化字节码、简化代码等操作;
3、混淆(obfuscate)使用简短的、无意义的名称重全名类名、方法名、字段等;
4、预校验(preverify)为class添加预校验信息。
运行环境:
jdk,不需要额外运行环境。
加密结果:
混淆后的class反编译后都是一些魔法命名字符,增加阅读难度。
ClassFinal
ClassFinal 是一款 Java class 文件安全加密工具,支持直接加密 jar 包或 war 包,无需修改任何项目代码,兼容 spring-framework,可避免源码泄漏或字节码被反编译。
项目模块说明:
1、classfinal-core: ClassFinalde 的核心模块,几乎所有加密的代码都在这里;
2、classfinal-fatjar: ClassFinal 打包成独立运行的 jar 包;
3、classfinal-maven-plugin: ClassFinal 加密的 maven 插件;
功能特性:
1、无需修改原项目代码,只要把编译好的 jar/war 包用本工具加密即可。
2、运行加密项目时,无需求修改 tomcat,spring 等源代码。
3、支持普通 jar 包、springboot jar 包以及普通 java web 项目编译的 war 包。
4、支持 spring framework、swagger 等需要在启动过程中扫描注解或生成字节码的框架。
5、支持 maven 插件,添加插件后在打包过程中自动加密。
6、支持加密 WEB-INF/lib 或 BOOT-INF/lib 下的依赖 jar 包。
环境依赖:
JDK 1.8 +
本工具使用 AES 算法加密 class 文件,密码是保证不被破解的关键,请保存好密码,请勿泄漏。
密码一旦忘记,项目不可启动且无法恢复,请牢记密码。
本工具加密后,原始的 class 文件并不会完全被加密,只是方法体被清空,保留方法参数、注解等信息,这是为了兼容 spring,swagger 等扫描注解的框架; 方法体被清空后,反编译者只能看到方法名和注解,看不到方法的具体内容;当 class 被 classloader 加载时,真正的方法体会被解密注入。
加密结果:
配置文件反编译后为空
class文件反编译后直接隐藏方法体
ClassFinal实战
由于我们不希望引入其他外部依赖环境,遂选择ClassFinal进行代码混淆,可以达到隐藏配置文件内容和清空方法体的效果,即使外部人员拿到源码也不能仿造系统。
纯命令方式
下载工具
https://repo1.maven.org/maven2/net/roseboy/classfinal-fatjar/1.2.1/classfinal-fatjar-1.2.1.jar
参数说明
-file 加密的jar/war完整路径
-packages 加密的包名(可为空,多个用","分割)
-libjars jar/war包lib下要加密jar文件名(可为空,多个用","分割)
-cfgfiles 需要加密的配置文件,一般是classes目录下的yml或properties文件(可为空,多个用","分割)
-exclude 排除的类名(可为空,多个用","分割)
-classpath 外部依赖的jar目录,例如/tomcat/lib(可为空,多个用","分割)
-pwd 加密密码,如果是#号,则使用无密码模式加密
-code 机器码,在绑定的机器生成,加密后只可在此机器上运行
-Y 无需确认,不加此参数会提示确认以上信息
执行以下命令
java -jar classfinal-fatjar-1.2.1.jar -file yourpaoject.jar -libjars a.jar,b.jar -packages com.yourpackage,com.yourpackage2 -exclude com.yourpackage.Main -pwd 123456 -Y
结果: 生成 yourpaoject-encrypted.jar,这个就是加密后的jar文件;加密后的文件不可直接执行,需要配置javaagent。
执行jar
java -javaagent:yourpaoject-encrypted.jar='-pwd 123456' -jar yourpaoject-encrypted.jar
maven插件方式
引入ClassFinal插件后直接package即可生成加密包
pom引入插件
<plugin>
<groupId>net.roseboy</groupId>
<artifactId>classfinal-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<password>#</password>
<packages>yourpackage</packages>
<excludes>org.spring</excludes>
<cfgfiles>yourconfig</cfgfiles>
<libjars>yourjar</libjars>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>classFinal</goal>
</goals>
</execution>
</executions>
</plugin>
mvn打包
mvn package -Dmaven.test.skip=true
反编译jar
配置文件全部清空
class文件方法体全部清空
依赖的lib包方法体全部清空
写在最后
非常重要的项目推荐使用XJar可以完全隐藏Class文件内容,但是需要额外的go环境支持,也可以保守选择ClassFinal直接无侵入达到隐藏方法体和配置文件内容的目的。当然任何的加密和代码混淆的方案都只是增加反编译破解难度,在实际的生产中还需要增加远程鉴权、机器码植入验证、远程依赖加载等等方式保证软件的控制权。