xjar 源碼流程分析

xjar

xjar是什麼

xjar的定義

  1. Spring Boot JAR 安全加密運行工具,同時支持的原生JAR。
  2. 基於對JAR包內資源的加密以及拓展ClassLoader來構建的一套程序加密啓動,動態解密運行的方案,避免源碼泄露或反編譯

功能特性

  • 無需侵入代碼,只需要把編譯好的JAR包通過工具加密即可。
  • 完全內存解密,杜絕源碼以及字節碼泄露或反編譯。
  • 支持所有JDK內置加解密算法。
  • 可選擇需要加解密的字節碼或其他資源文件,避免計算資源浪費。

xjar如何使用

xjar githubd地址:https://github.com/core-lib/xjar

導入依賴

    <dependencies>
        <!--核心庫-->
        <dependency>
            <groupId>com.github.core-lib</groupId>
            <artifactId>xjar</artifactId>
            <version>v2.0.6</version>
        </dependency>
        <!--用於讀取jar中的文件-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-compress</artifactId>
            <version>1.18</version>
        </dependency>
        <!--資源加載器-->
        <dependency>
            <groupId>com.github.core-lib</groupId>
            <artifactId>loadkit</artifactId>
            <version>v1.0.0</version>
        </dependency>
    </dependencies>

加密普通jar

	public static void main(String[] args) throws Exception {
		String password = args[0];
		XKey xKey = XKit.key(password);
		XJar.encrypt(args[1], args[2], xKey);
		System.out.println("Successfully generated encrypted jar");

	}

解密普通jar

	public static void main(String[] args) throws Exception {
		String password = args[0];
		XKey xKey = XKit.key(password);
		XJar.decrypt(args[1], args[2], xKey);
	}

普通的jar 使用XJar類 進行加密/解密

spring boot 項目使用Xboot 進行加密解密

執行 加密的jar

啓動參數說明
參數名稱 參數含義 缺省值 說明
–xjar.password 密碼
–xjar.algorithm 密鑰算法 AES 支持JDK所有內置算法,如AES / DES …
–xjar.keysize 密鑰長度 128 根據不同的算法選取不同的密鑰長度。
–xjar.ivsize 向量長度 128 根據不同的算法選取不同的向量長度。
–xjar.keyfile 密鑰文件 ./xjar.key 密鑰文件相對或絕對路徑。

啓動後提示輸入密碼

java -jar /path/to/encrypted.jar

通過傳參方式啓動

java -jar /path/to/encrypted.jar --xjar.password=PASSWORD

推薦啓動方式 nohup 後臺啓動 指定密鑰文件

nohup java -jar /path/to/encrypted.jar --xjar.keyfile=/path/to/xjar.key

密鑰文件參數說明
參數名稱 參數含義 缺省值 說明
password 密碼 密碼字符串
algorithm 密鑰算法 AES 支持JDK所有內置算法,如AES / DES …
keysize 密鑰長度 128 根據不同的算法選取不同的密鑰長度。
ivsize 向量長度 128 根據不同的算法選取不同的向量長度。
hold 是否保留 false 讀取後是否保留密鑰文件。

xjar原理探究

xjar 加密過程

img

xjar執行過程

img

jar 中的class 是如何解密的

自定義了 XJarClassLoader 繼承了 URLClassLoader

其中 XJarClassLoader 自定義了 XJarURLHandler 繼承與 URLStreamHandler

XJarURLHandler 用於對url進行處理,其中有個重要屬性 indexes

indexes 獲取jar 中的 XJAR-INF/INDEXES.IDX

XJarURLConnection 自定義了JarURLConnection 用於 自定義解密加密的類

XJarURLConnection.getInputStream() 獲取CipherInputStream

XJarClassLoader.findClass()

->super.findClass(name)出現ClassFormatError->

XJarClassLoader.findResource()->URL.openStream()

->URL.openConnection()->handler.openConnection();

當URL.openConnection() 就會調用 XJarURLHandler.openConnection()

根據class的url是否屬於indexes裏面的url , 屬於就使用XJarURLConnection 進行文件解密

XJarClassLoader.findClass() 如何被觸發的

xJarClassLoader = new XJarClassLoader(urlClassLoader.getURLs(), classLoader.getParent(), xLauncher.xDecryptor, xLauncher.xEncryptor, xLauncher.xKey);
 // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }

這裏寫圖片描述

  • 由於 XJarClassLoader 設置的父加載器爲 當前classLoader 的父加載器,爲ExtClassLoader

  • 基於雙親委派機制,父類加載器不會加載到 當前jar路徑下的class ,最後會調用XjarClassLoader的findClass()

  • XjarClassLoader.findClass()會先嚐試用URLClassLoader的findClass() 當出現ClassFormatError 則說明當前類可能是加密的, 會嘗試使用 自定義的解密方式進行類加載。

ss ,最後會調用XjarClassLoader的findClass()

  • XjarClassLoader.findClass()會先嚐試用URLClassLoader的findClass() 當出現ClassFormatError 則說明當前類可能是加密的, 會嘗試使用 自定義的解密方式進行類加載。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章