如何对jar包进行加密呢?其实没有想象中的那么困难,有一款开源工具已经提供了较为完善的加密方案,这款开源工具的名字叫做xjar。接下来我们就看一下使用xjar工具给jar包加密有多么的容易。
jar包相信大家都很熟悉,是通过打包java工程而获得的产物,但是jar包是有一个致命的缺点的,那就是很容易被反编译,只需要使用jd-gui就可以很容易的获取到java源码。
如果你想要防止别人反编译做逆向工程,那么对jar包进行一次加密就是一项很重要的工作了。
开源jar加密分为两种一种代码混淆,一种字节码转换。
字节码混淆,主要思路就是的对类名,变量名和方法名,局部参数名进行替换,让其命名变得无意义,很难读懂,但不影响其逻辑,但对于有耐心的人,还是能看明白!具体实现是在编译前做的混淆,还是编译后做的混淆,这个没用过不太清楚。
字节码转换,分为两块,一块是加密,对编译后class文件进行字节码转换(可以采用加密算法,字节码异或运算或自己定义规则);一块是解密,就是在类加载的时候对加密的字节码进行解密。加密这块因为在本地对class文件字节码转换,比较简单,方式也随意;解密这块主要围绕类加载器来做文章,又可分为java版实现和C/C++版实现,java版主要基于-agentJava:xxx.jar,通过Premain-Class,向Instrumentation注入ClassFileTransformer实现,自己在ClassFileTransformer中对需要解密的class文件进行解密;C/C++主要使用-agentpath:xxx.so,基于JVMTI通过C/C++实现,对类加载过程进行操作。
总体来说:代码混淆和字节码转换可以结合,例如,先代码混淆后,再对字节码加密,运行时对字节码解密。代码混淆,上手最简单,加密级别比较低,也容易破解。字节码转换,java版本对于java熟练人员上手很快,加密级别一般,个人理解该方式一个缺陷就是对于想加密的内容加密了,但解密方式暴露了,如果能够隐藏好解密方式,加密安全系数还是蛮高;C/C++版加密级别最高,但需要对java和C/C++都很熟练,而且需要研究JVMTI相关知识,如果真的实现了基本无破解风险,不过对于SpringBoot等框架,其内部会直接分析class文件,有些坑需要解决。
另外一个问题就是,使用jar加密这块,需要确定好是对运行的主程序jar包加密,还是第三方jar加密,其还是有部分差异的。
现在假设你的项目是一个maven项目(目前不使用maven的项目已经不多了),那么加密起来特别的容易,
首先就是要在你的pom文件中增加插件仓库地址,如下:
jitpack.io
https://jitpack.io
然后在pom文件中增加如下插件:
com.github.core-lib
xjar-maven-plugin
4.0.1
build
install
/com/huc/**/*.class
/mapper/**/*Mapper.xml
/*.yml
/templates/**.*
/static/**.*
这样,我们的准备工作就做完了,需要注意的是,includes代表我们想要加密的内容,采用的是Ant表达式,excludes代表的是不需要加密的内容,同样使用的Ant表达式。
一般情况下我们建议这两处内容必填,如果不填写,会加密整个jar包中的所有文件,这样其实是没有必要的,而且全部加密后启动的时候也可能产生意料之外的错误。
另外要说明的是,加密后的jar包是需要通过golang环境运行的,所以我们需要提前把golang的运行环境安装好,安装过程请自行百度。
现在我们就开始正式的加密工作了,加密过程非常简单,只需要使用maven的install命令即可自动打包,命令如下:
mvn clean install -Dxjar.password=password -Dmaven.test.skip=true
这里的password可以自行指定密码,是必填项。
执行后就会得到两个文件:一个是xjar.go的go源文件,一个是你项目的xjar包,也就是加密后的jar包。
运行加密后的jar包是需要先编译xjar.go源文件生成jar包启动器的。编译方式如下:
go build ./xjar.go
编译后会生成xjar.exe启动器(王子使用的是window系统,如果是linux系统就不是exe后缀了)。
之后使用如下命令即可运行加密后的jar包:
./xjar.exe java -jar ./**.xjar
可以看出,只是在使用java -jar的前边加上启动器即可,还是很方便的。
防止反编译只能防止jar包被逆向破解,如果想要限制用户的使用时间,按时间付费需要怎么做呢?
这就要说到license加密技术了,我们下篇文章就来说说如何在你的项目中增加license,限制用户的使用。
ClassFinal:Mr.K/ClassFinal
基于字节码转换java版,国人实现的,蛮不错的,对SpringBoot支持也好,其逻辑就是基于-agentJava:xxx.jar这一套原理,加密时对class文件做了两次处理,一次是对class文件的字节码完全加密,一次是对class文件混淆,这个混淆是保留成员和方法,对方法内部实现进行隐藏;解密时,判断如果该类是自己加密过的,找到完全加密的字节码进行解密,如果不是自己加密的就跳过。其对class文件混淆,就是方便类似SpringBoot等三方框架直接分析class文件。好处就是,如果你是个工具包,加密后给其它人,其他人编程时引用或者编译都不影响,但是运行时需要加密方支持,给出秘钥之类的。比较灵活和好用,也存在该方式的统一缺陷,不过其支持主程序jar加密,也支持单独的第三方工具jar加密。
JarEncrypt:https://github.com/zhikun0704/api-zxv-jvmit
基于字节码转换C/C++版,基于JVMIT个人实现的,稍微研究了下,其支持对部分class加密,对应一般java应用问题不大,但对于SpringBoot项目支持可能有些问题。因本人C++水平有限,没有深层次研究,希望有C/C++和java都熟悉的大神有空搞一套完整的。