|
|
@@ -20,6 +20,7 @@ import java.util.HashSet;
|
|
|
import java.util.Map;
|
|
|
import java.util.Objects;
|
|
|
import java.util.Set;
|
|
|
+import java.util.concurrent.ConcurrentHashMap;
|
|
|
import java.util.stream.Collectors;
|
|
|
import java.util.zip.ZipFile;
|
|
|
|
|
|
@@ -31,11 +32,11 @@ import java.util.zip.ZipFile;
|
|
|
*/
|
|
|
public class DecryptExecutor {
|
|
|
|
|
|
- /** 要解密的文件清单,记录已加密的class的全类名的清单文件 */
|
|
|
- private static Set<String> checklist;
|
|
|
+ /** key- projectPath; value-要解密的文件清单,记录已加密的class的全类名的清单文件 */
|
|
|
+ private static Map<String, Set<String>> checklist = new ConcurrentHashMap<>(8);
|
|
|
|
|
|
/**
|
|
|
- * 以key-value的形式记录lib中的被混淆的类(key-被混淆的类的无后缀全类名, value-存放采集到的类所在lib的信息的文件夹)。
|
|
|
+ * 以key-value的形式记录lib中的被混淆的类(key-被混淆的类的无后缀全类名, value-存放采集到的类所在lib的信息的文件夹)
|
|
|
*
|
|
|
* key - 形如: com.abc.xyz.Qwer
|
|
|
* value - 形如: META-INF/winter/abc-1.0.0_jar/
|
|
|
@@ -99,19 +100,18 @@ public class DecryptExecutor {
|
|
|
* @return classLongName是否在(记录已加密类的)清单列表中
|
|
|
*/
|
|
|
public static boolean checklistContain(String projectPath, String classLongName) {
|
|
|
- if (checklist == null) {
|
|
|
+ if (!checklist.containsKey(projectPath)) {
|
|
|
byte[] checklistByte = IOUtil.readFileFromWorkbenchRoot(new File(projectPath),
|
|
|
Constant.ALREADY_ENCRYPTED_CLASS_CHECKLIST_CLASSES_SAVE_FILE);
|
|
|
if (checklistByte == null) {
|
|
|
- checklist = new HashSet<>();
|
|
|
Logger.debug(DecryptExecutor.class, "checklistByte is null. ");
|
|
|
} else {
|
|
|
String checklistContent = new String(checklistByte, StandardCharsets.UTF_8);
|
|
|
Logger.debug(DecryptExecutor.class, "checklistContent " + checklistContent);
|
|
|
- checklist = new HashSet<>(Arrays.asList(checklistContent.split(Constant.COMMA)));
|
|
|
+ checklist.put(projectPath, new HashSet<>(Arrays.asList(checklistContent.split(Constant.COMMA))));
|
|
|
}
|
|
|
}
|
|
|
- return checklist.contains(classLongName);
|
|
|
+ return checklist.get(projectPath).contains(classLongName);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -175,12 +175,16 @@ public class DecryptExecutor {
|
|
|
/**
|
|
|
* 判断类classBytes是否被盖章
|
|
|
*
|
|
|
- * @param classBytes
|
|
|
- * 类的字节码
|
|
|
+ * @param projectPath 项目路径
|
|
|
+ * @param classBytes 类的字节码
|
|
|
* @return classBytes中是否存在加密印章
|
|
|
*/
|
|
|
- public static boolean verifySeal(byte[] classBytes) {
|
|
|
- return new String(classBytes, StandardCharsets.UTF_8).contains(Cache.sealCache);
|
|
|
+ public static boolean verifySeal(String projectPath, byte[] classBytes) {
|
|
|
+ String seal = Cache.sealCache.get(projectPath);
|
|
|
+ if (StrUtil.isBlank(seal)) {
|
|
|
+ throw new ClassWinterException("seal should not be blank. curr projectPath -> " + projectPath + ". curr sealCache is -> " + Cache.sealCache);
|
|
|
+ }
|
|
|
+ return new String(classBytes, StandardCharsets.UTF_8).contains(seal);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -263,10 +267,8 @@ public class DecryptExecutor {
|
|
|
/**
|
|
|
* 恢复非class文件的混淆
|
|
|
*
|
|
|
- * @param zipFilePath
|
|
|
- * 项目jar/war包路径
|
|
|
- * @param password
|
|
|
- * 项目加密密码(可能为null)
|
|
|
+ * @param zipFilePath 项目jar/war包路径
|
|
|
+ * @param password 项目加密密码(可能为null)
|
|
|
* @return 被替换了的ZipEntry的相对路径及重写前后的内容信息<br/>
|
|
|
* k - ZipEntry的相对路径,如:BOOT-INF/classes/application.yml<br/>
|
|
|
* v - 左:重写前的内容,右:重写后的内容
|
|
|
@@ -291,7 +293,7 @@ public class DecryptExecutor {
|
|
|
for (String zipEntryName : needToDecryptNonClassFileSet) {
|
|
|
// 只处理有印章的
|
|
|
byte[] cleanedBytes = IOUtil.readFileFromWorkbenchRoot(zipFile, zipEntryName);
|
|
|
- if (DecryptExecutor.verifySeal(cleanedBytes)) {
|
|
|
+ if (DecryptExecutor.verifySeal(zipFilePath, cleanedBytes)) {
|
|
|
byte[] encryptedBytes = IOUtil.readFileFromWorkbenchRoot(zipFile,
|
|
|
Constant.DEFAULT_ENCRYPTED_NON_CLASSES_SAVE_DIR + zipEntryName);
|
|
|
byte[] bytes = EncryptUtil.decrypt(encryptedBytes, userIfInputPwdWhileDecrypt ? password :
|
|
|
@@ -329,7 +331,7 @@ public class DecryptExecutor {
|
|
|
}
|
|
|
// 存时,是加密存进去的; 这里读取时,解密一下
|
|
|
passwordByte = EncryptUtil.decrypt(new String(passwordByte, StandardCharsets.UTF_8),
|
|
|
- Cache.sealCache.toCharArray()).getBytes(StandardCharsets.UTF_8);
|
|
|
+ Cache.sealCache.get(projectPath).toCharArray()).getBytes(StandardCharsets.UTF_8);
|
|
|
String password = new String(passwordByte, StandardCharsets.UTF_8);
|
|
|
char[] passwordCharArr = password.toCharArray();
|
|
|
// 放入缓存
|
|
|
@@ -348,7 +350,7 @@ public class DecryptExecutor {
|
|
|
Objects.requireNonNull(passwordByte);
|
|
|
// 存时,是加密存进去的; 这里读取时,解密一下
|
|
|
char[] passwordCharArr = EncryptUtil.decrypt(new String(passwordByte, StandardCharsets.UTF_8),
|
|
|
- Cache.sealCache.toCharArray()).toCharArray();
|
|
|
+ Cache.sealCache.get(projectPath).toCharArray()).toCharArray();
|
|
|
Cache.libPasswordCache.put(classWinterInfoDir, passwordCharArr);
|
|
|
return passwordCharArr;
|
|
|
}
|