一、概述
jar包被其他人拿走很容易编译出源代码,造成源代码泄露,影响程序安全。
参考地址:
1.1 常见的加密工具
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 加载时,真正的方法体会被解密注入。
加密结果: 配置文件反编译后为空
二、ClassFinal使用
1.1 打包后加密
使用ClassFinal的加密工具,直接将打包后的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执行后会在jar包的路径下生成一个 jar包名+encrypted.jar的文件
1.2 maven打包加密
maven打包加密是在打包后,为打包后的包再进行一次加密。因此,插件需要放置到打包的插件后边。
方式1:插件方式
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<!--
1. 加密后,方法体被清空,保留方法参数、注解等信息.主要兼容swagger文档注解扫描
2. 方法体被清空后,反编译只能看到方法名和注解,看不到方法体的具体内容
3. 加密后的项目需要设置javaagent来启动,启动过程中解密class,完全内存解密,不留下任何解密后的文件
4. 启动加密后的jar,生成xxx-encrypted.jar,这个就是加密后的jar文件,加密后不可直接执行
5. 无密码启动方式,java -javaagent:xxx-encrypted.jar -jar xxx-encrypted.jar
6. 有密码启动方式,java -javaagent:xxx-encrypted.jar='-pwd= 密码' -jar xxx-encrypted.jar
-->
<groupId>net.roseboy</groupId>
<artifactId>classfinal-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<password>#</password><!-- #表示启动时不需要密码,事实上对于代码混淆来说,这个密码没什么用,它只是一个启动密码 -->
<excludes>org.spring</excludes>
<packages>${groupId}</packages><!-- 加密的包名,多个包用逗号分开 -->
<cfgfiles>application.yml,application-dev.yml</cfgfiles><!-- 加密的配置文件,多个包用逗号分开 -->
<libjars>hutool-all.jar</libjars> <!-- jar包lib下面要加密的jar依赖文件,多个包用逗号分开 -->
<code>xxxx</code> <!-- 指定机器启动,机器码 -->
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>classFinal</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>方式2:插件执行命令方式
该方式原理是使用1.1的方式,将1.1的命令写成脚本,然后再生成jar包后,再对jar包进行加密。
需要将1.1的工具包 和脚本文件放置到项目根目录。
脚本文件:
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插件配置:(粘贴在打包插件后)
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>classfinal.bat</executable>
</configuration>
</plugin>1.3 jar包启动
加密后一般是后会在jar包的路径下生成一个 jar包名+encrypted.jar的文件
启动命令:
#无密码启动
java -javaagent:xxx-encrypted.jar -jar xxx-encrypted.jar
# 有密码启动
<NolebasePageProperties />
java -javaagent:xxx-encrypted.jar='-pwd=密码' -jar xxx-encrypted.jar1.4 绑定机器码
使用1.1的工具包,执行命令生成机器码:
java -jar classfinal-fatjar-1.2.1.jar -C