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 则说明当前类可能是加密的, 会尝试使用 自定义的解密方式进行类加载。

猜你喜欢

转载自blog.csdn.net/yumingzhu1/article/details/107151405