深度揭秘!Java Class 文件加密終極指南,有效保護你的核心代碼
前言
在某次聚餐中,朋友聊起他接了一個私單,他不想把他的核心代碼開放出去,但又想項目能正常運行。翻譯成技術術語就是他想對源碼進行混淆或者加密。之前我寫過一篇文章聊聊如何進行代碼混淆。今天我們來聊另一個的話題,聊聊如何利用ClassFinal對代碼進行加密。
ClassFinal
ClassFinal簡介
ClassFinal是一款java class文件安全加密工具,支持直接加密jar包或war包,無需修改任何項目代碼,兼容spring-framework;可避免源碼泄漏或字節碼被反編譯。
gitee地址:https://gitee.com/roseboy/classfinal
功能特性
- 無需修改原項目代碼,只要把編譯好的jar/war包用本工具加密即可。
- 運行加密項目時,無需求修改tomcat,spring等源代碼。
- 支持普通jar包、springboot jar包以及普通java web項目編譯的war包。
- 支持spring framework、swagger等需要在啟動過程中掃描注解或生成字節碼的框架。
- 支持maven插件,添加插件后在打包過程中自動加密。
- 支持加密WEB-INF/lib或BOOT-INF/lib下的依賴jar包。
- 支持綁定機器,項目加密后只能在特定機器運行。
- 支持加密springboot的配置文件。
項目模塊說明
- classfinal-core: ClassFinal的核心模塊,幾乎所有加密的代碼都在這里;
- classfinal-fatjar: ClassFinal打包成獨立運行的jar包;
- classfinal-maven-plugin: ClassFinal加密的maven插件;
如何使用
1、加密
方法一 使用classfinal-fatjar.jar
執行如下命令
java -jar classfinal-fatjar.jar -file yourproject.jar -libjars a.jar,b.jar -packages com.yourpackage,com.yourpackage2 -exclude com.yourpackage.Main -pwd 123456 -Y
參數說明
-file 加密的jar/war完整路徑
-packages 加密的包名(可為空,多個用","分割)
-libjars jar/war包lib下要加密jar文件名(可為空,多個用","分割)
-cfgfiles 需要加密的配置文件,一般是classes目錄下的yml或properties文件(可為空,多個用","分割)
-exclude 排除的類名(可為空,多個用","分割)
-classpath 外部依賴的jar目錄,例如/tomcat/lib(可為空,多個用","分割)
-pwd 加密密碼,如果是#號,則使用無密碼模式加密
-code 機器碼,在綁定的機器生成,加密后只可在此機器上運行
-Y 無需確認,不加此參數會提示確認以上信息
方法二: 使用classfinal-maven-plugin插件
在項目pom配置classfinal-maven-plugin插件
<plugin>
<groupId>net.roseboy</groupId>
<artifactId>classfinal-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<password>123456</password> <!--加密密碼,如果是#號,則使用無密碼模式加密-->
<packages>*</packages> <!--加密的包名(可為空,多個用","分割)-->
<cfgfiles>*.yml</cfgfiles> <!--需要加密的配置文件,一般是classes目錄下的yml或properties文件(可為空,多個用","分割)-->
<!--<libjars>oneclickedcrypt-1.0-SNAPSHOT.jar</libjars>--> <!--jar/war包lib下要加密jar文件名(可為空,多個用","分割)-->
<!--<cfgpasspath>/etc/.env</cfgpasspath>--> <!--密碼文件路徑,可為空,默認 /etc/.env-->
<!--<excludes>com.Test</excludes>--> <!--排除不需要加密的文件-->
<!--<classpath></classpath>--> <!--外部依賴jarlib-->
<!-- <debug>true</debug> --> <!--調試模式,打印debug日志-->
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>classFinal</goal>
</goals>
</execution>
</executions>
</plugin>
運行mvn package時會在target下自動加密生成yourproject-encrypted.jar,maven插件的參數名稱與直接運行的參數相同
注: 加密時-pwd參數設為#,啟動時可不用輸入密碼; 如果是war包,啟動時指定參數 -nopwd,跳過輸密碼過程。
加密后的效果示例
加密前:
@RestController
@RequestMapping("user")
@RequiredArgsConstructor
@Slf4j
public class UserController {
private final UserService userService;
@GetMapping("list")
public List<User> list(){
return userService.list();
}
}
加密后:
@RestController
@RequestMapping("user")
@RequiredArgsConstructor
@Slf4j
public class UserController {
private static final Logger log = LoggerFactory.getLogger(UserController.class);
private final UserService userService;
@GetMapping({"list"})
public List<User> list() {
return null;
}
}
加密前: yml文件內容

加密后: yml文件內容

加密后,yml文件內容會被清空
2、啟動加密后的jar
加密后的項目需要設置javaagent來啟動,項目在啟動過程中解密class,完全內存解密,不留下任何解密后的文件。
解密功能已經自動加入到 yourproject-encrypted.jar中,所以啟動時-javaagent與-jar相同,不需要額外的jar包。
啟動jar項目執行以下命令:
java -javaagent:yourproject-encrypted.jar='-pwd 123456' -jar yourproject-encrypted.jar
//參數說明
// -pwd 加密項目的密碼
// -pwdname 環境變量中密碼的名字
注: 該工具使用AES算法加密class文件,密碼是保證不被破解的關鍵,請保存好密碼,請勿泄漏。
密碼一旦忘記,項目不可啟動且無法恢復,請牢記密碼。
該工具加密后,原始的class文件并不會完全被加密,只是方法體被清空,保留方法參數、注解等信息,這是為了兼容spring,swagger等掃描注解的框架; 方法體被清空后,反編譯者只能看到方法名和注解,看不到方法的具體內容;當class被classloader加載時,真正的方法體會被解密注入。
為了保證項目在運行時的安全,啟動jvm時請加參數: -XX:+DisableAttachMechanism 。
總結
本文介紹了如何利用ClassFinal對代碼進行加密。這個工具類在使用上可以說非常簡單,不過有點可惜,這個項目目前已經不再維護,有其他網友基于ClassFinal進行改造,開源了class-winter,感興趣的朋友可以查看如下網址https://gitee.com/JustryDeng/class-winter
demo鏈接
https://github.com/lyb-geek/springboot-learning/tree/master/springboot-encrypt

浙公網安備 33010602011771號