博客 / 詳情

返回

深度揭秘!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

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.