|
|
@@ -76,7 +76,6 @@ public class EncryptExecutor {
|
|
|
CLASS_WINTER_FILES.add(IOUtil.class.getName().replace(".", "/") + Constant.CLASS_SUFFIX);
|
|
|
CLASS_WINTER_FILES.add(JarUtil.class.getName().replace(".", "/") + Constant.CLASS_SUFFIX);
|
|
|
CLASS_WINTER_FILES.add(JavaagentCmdArgs.class.getName().replace(".", "/") + Constant.CLASS_SUFFIX);
|
|
|
- CLASS_WINTER_FILES.add(JavassistUtil.class.getName().replace(".", "/") + Constant.CLASS_SUFFIX);
|
|
|
CLASS_WINTER_FILES.add(Logger.class.getName().replace(".", "/") + Constant.CLASS_SUFFIX);
|
|
|
CLASS_WINTER_FILES.add(Pair.class.getName().replace(".", "/") + Constant.CLASS_SUFFIX);
|
|
|
CLASS_WINTER_FILES.add(PathUtil.class.getName().replace(".", "/") + Constant.CLASS_SUFFIX);
|
|
|
@@ -109,7 +108,6 @@ public class EncryptExecutor {
|
|
|
*/
|
|
|
private final String password;
|
|
|
|
|
|
-
|
|
|
/**
|
|
|
* 要加密的xml文件的zipEntry名前缀(如:)
|
|
|
*/
|
|
|
@@ -124,7 +122,6 @@ public class EncryptExecutor {
|
|
|
* xml中要清除的(根节点的)子节点名称
|
|
|
*/
|
|
|
private final Set<String> toCleanXmlChildElementNameSet;
|
|
|
-
|
|
|
|
|
|
/**
|
|
|
* 要加密的类的全类名前缀(也可以精确匹配)
|
|
|
@@ -251,65 +248,66 @@ public class EncryptExecutor {
|
|
|
|
|
|
// step0. 解压jar到jarRootDir下
|
|
|
String lastStep = "step13";
|
|
|
- showProcess("step00", lastStep, "un-jar-war");
|
|
|
List<String> filePathList = JarUtil.unJarWar(originJarOrWar, targetRootDir);
|
|
|
+ showProcess("step00", lastStep, "un-jar-war");
|
|
|
|
|
|
- showProcess("step01", lastStep, "clean-xml-files");
|
|
|
+ // step1. 混淆xml
|
|
|
File targetRootDirFile = new File(targetRootDir);
|
|
|
if (includeXmlPrefixSet != null && includeXmlPrefixSet.size() > 0) {
|
|
|
cleanXmlFiles(filePathList, targetRootDirFile);
|
|
|
}
|
|
|
+ showProcess("step01", lastStep, "clean-xml-files");
|
|
|
|
|
|
- // step1. jar中的某些lib可能也需要加密,这里先(将那些需要加密的lib)进行解压,(解压到对应的临时目录,以便后面进行加密处理)
|
|
|
- showProcess("step02", lastStep, "un-lib-jar");
|
|
|
+ // step2. jar中的某些lib可能也需要加密,这里先(将那些需要加密的lib)进行解压,(解压到对应的临时目录,以便后面进行加密处理)
|
|
|
unLibJar();
|
|
|
+ showProcess("step02", lastStep, "un-lib-jar");
|
|
|
|
|
|
- // step2. 找到需要加密混淆的class文件
|
|
|
- showProcess("step03", lastStep, "filter-classes");
|
|
|
+ // step3. 找到需要加密混淆的class文件
|
|
|
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
|
|
|
+ // step4.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的全类名的清单文件
|
|
|
+ // step4.2. 生成记录已加密class的全类名的清单文件
|
|
|
generateChecklistFile(allAlreadyEncryptedClassFileList);
|
|
|
+ showProcess("step04", lastStep, "encrypt-classes");
|
|
|
|
|
|
- // step4. 记录印章(在解密时,可通过 checklist + 印章 判断一个class是否是被class-winter加密过)
|
|
|
- showProcess("step05", lastStep, "record-seal");
|
|
|
+ // step5. 记录印章(在解密时,可通过 checklist + 印章 判断一个class是否是被class-winter加密过)
|
|
|
generateSealFile();
|
|
|
+ showProcess("step05", lastStep, "record-seal");
|
|
|
|
|
|
- // step5. 设置启动jar包时需要检查的jvm参数项
|
|
|
- showProcess("step06", lastStep, "setting-jvm-arg-check-items");
|
|
|
+ // step6. 设置启动jar包时需要检查的jvm参数项
|
|
|
settingJvmArgCheckItems();
|
|
|
+ showProcess("step06", lastStep, "setting-jvm-arg-check-items");
|
|
|
|
|
|
- // step6. 混淆原.class文件(即:清空方法体)
|
|
|
+ // step7. 混淆原.class文件(即:清空方法体)
|
|
|
clearClassMethod(allNeedEncryptedClassFileList);
|
|
|
showProcess("step07", lastStep, "clear-class-method");
|
|
|
|
|
|
- // step7. 清除META-INF/maven下pom.xml中关于class-winter-plugin的相关信息
|
|
|
+ // step8. 清除META-INF/maven下pom.xml中关于class-winter-plugin的相关信息
|
|
|
clearWinterPluginInfo();
|
|
|
showProcess("step08", lastStep, "clear-winter-plugin-info");
|
|
|
|
|
|
- // step8. 添加class-winter的用于javaagent解密的代码
|
|
|
+ // step9. 添加class-winter的用于javaagent解密的代码
|
|
|
addClassWinterAgent();
|
|
|
showProcess("step09", lastStep, "add-class-winter-agent");
|
|
|
|
|
|
- // step9. 汇总那些在本次加密前本身就已经是被class-winter混淆的lib的相关信息到当前项目中
|
|
|
+ // step10. 汇总那些在本次加密前本身就已经是被class-winter混淆的lib的相关信息到当前项目中
|
|
|
collectAlreadyProtectedLibInfo();
|
|
|
showProcess("step10", lastStep, "collect-already-protected-lib-info");
|
|
|
|
|
|
- // step10. 与step1项对应,将临时目录还原为原来的lib(此时得到的lib是加密后的)
|
|
|
+ // step11. 与step2项对应,将临时目录还原为原来的lib(此时得到的lib是加密后的)
|
|
|
doLibJar();
|
|
|
showProcess("step11", lastStep, "do-lib-jar");
|
|
|
|
|
|
- // step11. 压缩targetRootDir目录为绝对文件路径名为generatedJarWar的jar(or war)包
|
|
|
+ // step12. 压缩targetRootDir目录为绝对文件路径名为generatedJarWar的jar(or war)包
|
|
|
String generatedJarWar = generateJarWarPath(this.originIsJar);
|
|
|
JarUtil.doJarWar(targetRootDir, generatedJarWar, new SimpleFileOrderSupport(filePathList));
|
|
|
showProcess("step12", lastStep, "generate-jar-war-path");
|
|
|
|
|
|
- // step12. 删除临时目录
|
|
|
+ // step13. 删除临时目录
|
|
|
IOUtil.delete(targetRootDirFile);
|
|
|
showProcess(lastStep, lastStep, "delete-tmp-dir");
|
|
|
return generatedJarWar;
|
|
|
@@ -688,7 +686,7 @@ public class EncryptExecutor {
|
|
|
}
|
|
|
content = sb.toString();
|
|
|
}
|
|
|
- Logger.debug(EncryptExecutor.class, "SeDtting jvmArgCheckItems -> " + content);
|
|
|
+ Logger.debug(EncryptExecutor.class, "Setting jvmArgCheckItems -> " + content);
|
|
|
byte[] encryptedBytes = EncryptUtil.encrypt(content.getBytes(StandardCharsets.UTF_8), obtainPassword());
|
|
|
IOUtil.toFile(Base64.getEncoder().encode(encryptedBytes), new File(targetRootDir, Constant.JVM_ARG_CHECK_FILE), true);
|
|
|
}
|
|
|
@@ -812,17 +810,56 @@ public class EncryptExecutor {
|
|
|
if (depth <= 0) {
|
|
|
return null;
|
|
|
}
|
|
|
+
|
|
|
+ // 从异常链中直接寻找NotFoundException
|
|
|
Throwable cause = e.getCause();
|
|
|
+ NotFoundException notFoundException = null;
|
|
|
for (int i = 0; i < depth; i++) {
|
|
|
if (cause instanceof NotFoundException) {
|
|
|
- return (NotFoundException)cause;
|
|
|
+ notFoundException = (NotFoundException)cause;
|
|
|
+ break;
|
|
|
}
|
|
|
if (cause == null) {
|
|
|
- return null;
|
|
|
+ break;
|
|
|
}
|
|
|
cause = cause.getCause();
|
|
|
}
|
|
|
- return null;
|
|
|
+ if (notFoundException != null) {
|
|
|
+ return notFoundException;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 从异常信息中寻找NotFoundException
|
|
|
+ cause = e;
|
|
|
+ depth = depth + 1;
|
|
|
+ for (int i = 0; i < depth; i++) {
|
|
|
+ if (cause == null) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ notFoundException = findFromMessage(cause.getMessage());
|
|
|
+ if (notFoundException != null) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ cause = cause.getCause();
|
|
|
+ }
|
|
|
+ return notFoundException;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从异常信息中寻找NotFoundException
|
|
|
+ *
|
|
|
+ * @param message 异常信息
|
|
|
+ *
|
|
|
+ * @return NotFoundException异常(null-则表示未找到)
|
|
|
+ */
|
|
|
+ private static NotFoundException findFromMessage(String message) {
|
|
|
+ if (message == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ if (!message.contains(Constant.NOT_FOUND_EXCEPTION_FLAG)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ String targetClassName = message.substring(message.indexOf(Constant.NOT_FOUND_EXCEPTION_FLAG) + (Constant.NOT_FOUND_EXCEPTION_FLAG).length()).trim();
|
|
|
+ return new NotFoundException(targetClassName);
|
|
|
}
|
|
|
|
|
|
/**
|