package com.whyc;
|
|
|
import com.whyc.util.*;
|
import com.whyc.util.*;
|
|
import java.io.ByteArrayInputStream;
|
import java.io.File;
|
import java.io.InputStream;
|
|
/**
|
* java class解密
|
*
|
* @author perry
|
*/
|
public class JarDecryptor {
|
//单例
|
private static final JarDecryptor single = new JarDecryptor();
|
//机器码
|
private char[] code;
|
//加密后文件存放位置
|
private static final String ENCRYPT_PATH = "META-INF/" + Const.FILE_NAME + "/";
|
|
//加密后文件存放位置
|
private static final String DESCRIPTION_PATH = "META-INF/";
|
|
/**
|
* 单例
|
*
|
* @return 单例
|
*/
|
public static JarDecryptor getInstance() {
|
return single;
|
}
|
|
/**
|
* 构造
|
*/
|
public JarDecryptor() {
|
this.code = SysUtils.makeMarchinCode();
|
}
|
|
/**
|
* 根据名称解密出一个文件
|
*
|
* @param projectPath 项目所在的路径
|
* @param fileName 文件名
|
* @param password 密码
|
* @return 解密后的字节
|
*/
|
public byte[] doDecrypt(String projectPath, String fileName, char[] password) {
|
long t1 = System.currentTimeMillis();
|
File workDir = new File(projectPath);
|
byte[] bytes = readEncryptedFile(workDir, fileName);
|
if (bytes == null) {
|
return null;
|
}
|
|
//读取机器码,有机器码,先用机器码解密
|
byte[] codeBytes = readEncryptedFile(workDir, Const.CONFIG_CODE);
|
if (codeBytes != null) {
|
//本机器码和打包的机器码不匹配
|
if (!StrUtils.equal(EncryptUtils.md5(this.code), StrUtils.toChars(codeBytes))) {
|
Log.println("该项目不可在此机器上运行!\n");
|
System.exit(-1);
|
}
|
|
//用机器码解密
|
char[] pass = StrUtils.merger(fileName.toCharArray(), code);
|
bytes = EncryptUtils.de(bytes, pass, Const.ENCRYPT_TYPE);
|
}
|
|
//无密码启动,读取隐藏的密码
|
if (password.length == 1 && password[0] == '#') {
|
password = readPassFromJar(workDir);
|
}
|
|
//密码解密
|
char[] pass = StrUtils.merger(password, fileName.toCharArray());
|
bytes = EncryptUtils.de(bytes, pass, Const.ENCRYPT_TYPE);
|
|
long t2 = System.currentTimeMillis();
|
Log.debug("解密: " + fileName + " (" + (t2 - t1) + " ms)");
|
|
return bytes;
|
|
}
|
|
/**
|
* 在jar文件或目录中读取文件字节
|
*
|
* @param workDir jar文件或目录
|
* @param name 文件名
|
* @return 文件字节数组
|
*/
|
public static byte[] readEncryptedFile(File workDir, String name) {
|
byte[] bytes = null;
|
String fileName = ENCRYPT_PATH + name;
|
//jar文件
|
if (workDir.isFile()) {
|
bytes = JarUtils.getFileFromJar(workDir, fileName);
|
} else {//war解压的目录
|
File file = new File(workDir, fileName);
|
if (file.exists()) {
|
bytes = IoUtils.readFileToByte(file);
|
}
|
}
|
return bytes;
|
}
|
|
/**
|
* 在jar文件或目录中读取密码字节
|
*
|
* @param workDir jar文件或目录
|
* @param name 文件名
|
* @return 文件字节数组
|
*/
|
public static byte[] readEncryptedFile2(File workDir, String name) {
|
byte[] bytes = null;
|
String fileName = DESCRIPTION_PATH + name;
|
//jar文件
|
if (workDir.isFile()) {
|
bytes = JarUtils.getFileFromJar(workDir, fileName);
|
} else {//war解压的目录
|
File file = new File(workDir, fileName);
|
if (file.exists()) {
|
bytes = IoUtils.readFileToByte(file);
|
}
|
}
|
return bytes;
|
}
|
|
/**
|
* 读取隐藏在jar的密码
|
*
|
* @param workDir jar路径
|
* @return 密码char
|
*/
|
public static char[] readPassFromJar(File workDir) {
|
byte[] passbyte = readEncryptedFile(workDir, Const.CONFIG_PASS);
|
if (passbyte != null) {
|
char[] pass = StrUtils.toChars(passbyte);
|
return EncryptUtils.md5(pass);
|
}
|
return null;
|
}
|
|
/**
|
* 读取隐藏在jar的密码
|
*
|
* @param workDir jar路径
|
* @return 密码char
|
*/
|
public static char[] readPassFromJar2(File workDir) {
|
byte[] passbyte = readEncryptedFile2(workDir, Const.FILE_NAME2);
|
if (passbyte != null) {
|
char[] pass = StrUtils.toChars(passbyte);
|
return EncryptUtils.md5(pass);
|
}
|
return null;
|
}
|
|
/**
|
* 解密配置文件,spring读取文件时调用
|
*
|
* @param path 配置文件路径
|
* @param in 输入流
|
* @return 解密的输入流
|
*/
|
public InputStream decryptConfigFile(String path, InputStream in, char[] pass) {
|
if (path.endsWith(".class")) {
|
return in;
|
}
|
String projectPath = JarUtils.getRootPath(null);
|
if (StrUtils.isEmpty(projectPath)) {
|
return in;
|
}
|
byte[] bytes = null;
|
try {
|
bytes = IoUtils.toBytes(in);
|
} catch (Exception e) {
|
|
}
|
if (bytes == null || bytes.length == 0) {//需要解密
|
bytes = this.doDecrypt(projectPath, path, pass);
|
}
|
if (bytes == null) {
|
return in;
|
}
|
in = new ByteArrayInputStream(bytes);
|
return in;
|
}
|
|
}
|