xjar 源码流程分析

文章目录

  • xjar
    • xjar是什么
      • xjar的定义
        • 功能特性
    • xjar如何使用
        • 导入依赖
        • 加密普通jar
        • 解密普通jar
        • 执行 加密的jar
          • 启动参数说明
          • 密钥文件参数说明
    • xjar原理探究
      • xjar 加密过程
      • xjar执行过程
      • jar 中的class 是如何解密的
        • XJarClassLoader.findClass() 如何被触发的

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-libgroupId>
            <artifactId>xjarartifactId>
            <version>v2.0.6version>
        dependency>
        
        <dependency>
            <groupId>org.apache.commonsgroupId>
            <artifactId>commons-compressartifactId>
            <version>1.18version>
        dependency>
        
        <dependency>
            <groupId>com.github.core-libgroupId>
            <artifactId>loadkitartifactId>
            <version>v1.0.0version>
        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 加密过程

xjar 源码流程分析_第1张图片

xjar执行过程

xjar 源码流程分析_第2张图片

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

你可能感兴趣的:(xjar,源码分析,java)