|
|
@@ -191,6 +191,11 @@ public class EncryptExecutor {
|
|
|
*/
|
|
|
private final String supportFile;
|
|
|
|
|
|
+ /**
|
|
|
+ * 在启动jar包时,需要进行的jvm输入参数校验
|
|
|
+ */
|
|
|
+ private final Set<String> jvmStartCheckSet;
|
|
|
+
|
|
|
/**
|
|
|
* 要加密的lib jar文件的绝对路径 & 其对应的加密临时目录
|
|
|
* 如: /xyz/abc.jar 与 /xyz/abc__temp__
|
|
|
@@ -201,7 +206,7 @@ public class EncryptExecutor {
|
|
|
String targetLibDir, String targetClassesDir, String password,
|
|
|
Set<String> includeXmlPrefixSet, Set<String> excludeXmlPrefixSet, Set<String> toCleanXmlChildElementNameSet,
|
|
|
Set<String> includePrefixSet, Set<String> excludePrefixSet, Set<String> includeLibSet,
|
|
|
- Set<Pair<String, String>> alreadyProtectedLibSet, String supportFile) {
|
|
|
+ Set<Pair<String, String>> alreadyProtectedLibSet, String supportFile, Set<String> jvmStartCheckSet) {
|
|
|
this.originJarOrWar = originJarOrWar;
|
|
|
this.originIsJar = originIsJar;
|
|
|
this.finalName = finalName;
|
|
|
@@ -217,6 +222,7 @@ public class EncryptExecutor {
|
|
|
this.includeLibSet = includeLibSet;
|
|
|
this.alreadyProtectedLibSet = alreadyProtectedLibSet;
|
|
|
this.supportFile = supportFile;
|
|
|
+ this.jvmStartCheckSet = jvmStartCheckSet;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -229,62 +235,66 @@ public class EncryptExecutor {
|
|
|
Logger.debug(EncryptExecutor.class, "Generate seal -> " + Constant.SEAL);
|
|
|
|
|
|
// step0. 解压jar到jarRootDir下
|
|
|
- List<String> filePathList = JarUtil.unJarWar(originJarOrWar, targetRootDir);
|
|
|
- String lastStep = "step12";
|
|
|
+ String lastStep = "step13";
|
|
|
showProcess("step00", lastStep, "un-jar-war");
|
|
|
+ List<String> filePathList = JarUtil.unJarWar(originJarOrWar, targetRootDir);
|
|
|
|
|
|
+ showProcess("step01", lastStep, "clean-xml-files");
|
|
|
File targetRootDirFile = new File(targetRootDir);
|
|
|
if (includeXmlPrefixSet != null && includeXmlPrefixSet.size() > 0) {
|
|
|
cleanXmlFiles(filePathList, targetRootDirFile);
|
|
|
}
|
|
|
- showProcess("step01", lastStep, "clean-xml-files");
|
|
|
|
|
|
// step1. jar中的某些lib可能也需要加密,这里先(将那些需要加密的lib)进行解压,(解压到对应的临时目录,以便后面进行加密处理)
|
|
|
- unLibJar();
|
|
|
showProcess("step02", lastStep, "un-lib-jar");
|
|
|
+ unLibJar();
|
|
|
|
|
|
// step2. 找到需要加密混淆的class文件
|
|
|
+ showProcess("step03", lastStep, "filter-classes");
|
|
|
List<File> allFiles = IOUtil.listSubFile(targetRootDirFile, 1);
|
|
|
List<File> allNeedEncryptedClassFileList = filterClasses(allFiles);
|
|
|
- showProcess("step03", lastStep, "filter-classes");
|
|
|
|
|
|
+ showProcess("step04", lastStep, "encrypt-classes");
|
|
|
// step3.1. 根据原.class文件,生成加密后的.class文件,并存至Constant.ENCRYPTED_CLASSES_SAVE_DIR
|
|
|
List<String> allAlreadyEncryptedClassFileList = encryptClasses(allNeedEncryptedClassFileList, new File(targetRootDir,
|
|
|
Constant.DEFAULT_ENCRYPTED_CLASSES_SAVE_DIR));
|
|
|
// step3.2. 生成记录已加密class的全类名的清单文件
|
|
|
generateChecklistFile(allAlreadyEncryptedClassFileList);
|
|
|
- showProcess("step04", lastStep, "un-jar-war");
|
|
|
|
|
|
// step4. 记录印章(在解密时,可通过 checklist + 印章 判断一个class是否是被class-winter加密过)
|
|
|
+ showProcess("step05", lastStep, "record-seal");
|
|
|
generateSealFile();
|
|
|
- showProcess("step05", lastStep, "encrypt-classes");
|
|
|
|
|
|
- // step5. 混淆原.class文件(即:清空方法体)
|
|
|
+ // step5. 记录sss(在解密时,可通过 checklist + 印章 判断一个class是否是被class-winter加密过)
|
|
|
+ showProcess("step06", lastStep, "record-jvm-start-check-items");
|
|
|
+ generateJvmStartCheckItems();
|
|
|
+
|
|
|
+ // step6. 混淆原.class文件(即:清空方法体)
|
|
|
clearClassMethod(allNeedEncryptedClassFileList);
|
|
|
- showProcess("step06", lastStep, "clear-class-method");
|
|
|
+ showProcess("step07", lastStep, "clear-class-method");
|
|
|
|
|
|
- // step6. 清除META-INF/maven下pom.xml中关于class-winter-plugin的相关信息
|
|
|
+ // step7. 清除META-INF/maven下pom.xml中关于class-winter-plugin的相关信息
|
|
|
clearWinterPluginInfo();
|
|
|
- showProcess("step07", lastStep, "clear-winter-plugin-info");
|
|
|
+ showProcess("step08", lastStep, "clear-winter-plugin-info");
|
|
|
|
|
|
- // step7. 添加class-winter的用于javaagent解密的代码
|
|
|
+ // step8. 添加class-winter的用于javaagent解密的代码
|
|
|
addClassWinterAgent();
|
|
|
- showProcess("step08", lastStep, "add-class-winter-agent");
|
|
|
+ showProcess("step09", lastStep, "add-class-winter-agent");
|
|
|
|
|
|
- // step8. 汇总那些在本次加密前本身就已经是被class-winter混淆的lib的相关信息到当前项目中
|
|
|
+ // step9. 汇总那些在本次加密前本身就已经是被class-winter混淆的lib的相关信息到当前项目中
|
|
|
collectAlreadyProtectedLibInfo();
|
|
|
- showProcess("step09", lastStep, "collect-already-protected-lib-info");
|
|
|
+ showProcess("step10", lastStep, "collect-already-protected-lib-info");
|
|
|
|
|
|
- // step9. 与step1项对应,将临时目录还原为原来的lib(此时得到的lib是加密后的)
|
|
|
+ // step10. 与step1项对应,将临时目录还原为原来的lib(此时得到的lib是加密后的)
|
|
|
doLibJar();
|
|
|
- showProcess("step10", lastStep, "do-lib-jar");
|
|
|
+ showProcess("step11", lastStep, "do-lib-jar");
|
|
|
|
|
|
- // step10. 压缩targetRootDir目录为绝对文件路径名为generatedJarWar的jar(or war)包
|
|
|
+ // step11. 压缩targetRootDir目录为绝对文件路径名为generatedJarWar的jar(or war)包
|
|
|
String generatedJarWar = generateJarWarPath(this.originIsJar);
|
|
|
JarUtil.doJarWar(targetRootDir, generatedJarWar, new SimpleFileOrderSupport(filePathList));
|
|
|
- showProcess("step11", lastStep, "generate-jar-war-path");
|
|
|
+ showProcess("step12", lastStep, "generate-jar-war-path");
|
|
|
|
|
|
- // step11. 删除临时目录
|
|
|
+ // step12. 删除临时目录
|
|
|
IOUtil.delete(targetRootDirFile);
|
|
|
showProcess(lastStep, lastStep, "delete-tmp-dir");
|
|
|
return generatedJarWar;
|
|
|
@@ -632,6 +642,26 @@ public class EncryptExecutor {
|
|
|
IOUtil.writeContentToFile(Constant.SEAL, new File(targetRootDir, Constant.SEAL_FILE));
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 生成记录启动jar包时需要检查的输入参数项文件
|
|
|
+ */
|
|
|
+ private void generateJvmStartCheckItems() {
|
|
|
+ String content;
|
|
|
+ if (jvmStartCheckSet == null || jvmStartCheckSet.size() == 0) {
|
|
|
+ content = Constant.JVM_START_CHECK_NO_ITEM_CONTENT;
|
|
|
+ } else {
|
|
|
+ StringBuilder sb = new StringBuilder(64);
|
|
|
+ for (String checkItem : jvmStartCheckSet) {
|
|
|
+ sb.append(checkItem).append(Constant.WHITE_SPACE);
|
|
|
+ }
|
|
|
+ content = sb.toString();
|
|
|
+ }
|
|
|
+ Logger.debug(EncryptExecutor.class, "Generate jvmStartCheckItems -> " + content);
|
|
|
+// content = Base64.getEncoder().encodeToString(content.getBytes(StandardCharsets.UTF_8));
|
|
|
+// final byte[] encryptedBytes = EncryptUtil.encrypt(content.getBytes(StandardCharsets.UTF_8), obtainPassword());
|
|
|
+ IOUtil.toFile(content.getBytes(StandardCharsets.UTF_8), new File(targetRootDir, Constant.JVM_START_CHECK_FILE), true);
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 添加class-winter的用于javaagent解密的代码
|
|
|
*/
|
|
|
@@ -904,6 +934,7 @@ public class EncryptExecutor {
|
|
|
// 密码脱敏
|
|
|
", password='" + (StrUtil.isBlank(password) ? null : "******") + '\'' +
|
|
|
", supportFile='" + supportFile + '\'' +
|
|
|
+ ", jvmStartCheckSet='" + jvmStartCheckSet + '\'' +
|
|
|
", includePrefixSet=" + includePrefixSet +
|
|
|
", excludePrefixSet=" + excludePrefixSet +
|
|
|
", includeXmlPrefixSet=" + includeXmlPrefixSet +
|
|
|
@@ -945,6 +976,8 @@ public class EncryptExecutor {
|
|
|
|
|
|
private String supportFile;
|
|
|
|
|
|
+ private String jvmStartCheck;
|
|
|
+
|
|
|
private Boolean debug = false;
|
|
|
|
|
|
private String tips;
|
|
|
@@ -1004,6 +1037,11 @@ public class EncryptExecutor {
|
|
|
return this;
|
|
|
}
|
|
|
|
|
|
+ public Builder jvmStartCheck(String jvmStartCheck) {
|
|
|
+ this.jvmStartCheck = jvmStartCheck;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
public Builder debug(Boolean debug) {
|
|
|
this.debug = debug;
|
|
|
return this;
|
|
|
@@ -1103,11 +1141,13 @@ public class EncryptExecutor {
|
|
|
|
|
|
// xml相关参数解析
|
|
|
Set<String> includeXmlPrefixSet = StrUtil.strToSet(includeXmlPrefix);
|
|
|
+ Set<String> jvmStartCheckSet = StrUtil.strToSet(jvmStartCheck);
|
|
|
Set<String> excludeXmlPrefixSet = StrUtil.strToSet(excludeXmlPrefix);
|
|
|
toCleanXmlChildElementName = StrUtil.isBlank(toCleanXmlChildElementName) ? Constant.DEFAULT_XML_NODE_NAMES : toCleanXmlChildElementName;
|
|
|
Set<String> toCleanXmlChildElementNameSet = StrUtil.strToSet(toCleanXmlChildElementName);
|
|
|
return new EncryptExecutor(this.originJarOrWar, originIsJar, this.finalName, targetRootDir, targetLibDir, targetClassesDir,
|
|
|
- password, includeXmlPrefixSet, excludeXmlPrefixSet, toCleanXmlChildElementNameSet, includePrefixSet, excludePrefixSet, includeLibSet, alreadyProtectedLibSet, this.supportFile);
|
|
|
+ password, includeXmlPrefixSet, excludeXmlPrefixSet, toCleanXmlChildElementNameSet, includePrefixSet,
|
|
|
+ excludePrefixSet, includeLibSet, alreadyProtectedLibSet, this.supportFile, jvmStartCheckSet);
|
|
|
}
|
|
|
|
|
|
/**
|