1.内置密码解码,多重密码混淆
2.外部运行虚假密码(未生效密码混淆)
| | |
| | | |
| | | //加密出来的文件名 |
| | | public static final String FILE_NAME = ".classes"; |
| | | //密码文件 |
| | | public static final String FILE_NAME2 = "launch_imp.dll"; |
| | | //密码 |
| | | public static final String FILE_NAME2_DESCRIPTION = "active code"; |
| | | |
| | | //AES 16为key |
| | | public static final String AES_KEY="wuhanyuanchangco"; |
| | | |
| | | //lib下的jar解压的目录名后缀 |
| | | public static final String LIB_JAR_DIR = "__temp__"; |
| | |
| | | import java.io.Console; |
| | | import java.io.File; |
| | | import java.lang.instrument.Instrumentation; |
| | | import java.nio.charset.Charset; |
| | | |
| | | |
| | | /** |
| | |
| | | char[] pwd; |
| | | |
| | | //读取jar隐藏的密码,无密码启动模式(jar) |
| | | pwd = JarDecryptor.readPassFromJar(new File(JarUtils.getRootPath(null))); |
| | | //pwd = JarDecryptor.readPassFromJar(new File(JarUtils.getRootPath(null))); |
| | | pwd = JarDecryptor.readPassFromJar2(new File(JarUtils.getRootPath(null))); |
| | | |
| | | if (args != null) { |
| | | options.parse(args.split(" ")); |
| | |
| | | } |
| | | |
| | | //验证密码,jar包是才验证 |
| | | byte[] passHash = JarDecryptor.readEncryptedFile(new File(JarUtils.getRootPath(null)), Const.CONFIG_PASSHASH); |
| | | /*System.out.println("验证jar,密码路径"+JarUtils.getRootPath(null)); |
| | | byte[] passHash = JarDecryptor.readEncryptedFile2(new File(JarUtils.getRootPath(null)),Const.FILE_NAME2); |
| | | if (passHash != null) { |
| | | char[] p1 = StrUtils.toChars(passHash); |
| | | char[] p1 = StrUtils.merger(pwd, EncryptUtils.SALT); |
| | | char[] p2 = EncryptUtils.md5(StrUtils.merger(pwd, EncryptUtils.SALT)); |
| | | p2 = EncryptUtils.md5(StrUtils.merger(EncryptUtils.SALT, p2)); |
| | | if (!StrUtils.equal(p1, p2)) { |
| | | Log.println("\nERROR: Startup failed, invalid password.\n"); |
| | | System.exit(0); |
| | | } |
| | | }*/ |
| | | byte[] pwdHash = JarDecryptor.readEncryptedFile2(new File(JarUtils.getRootPath(null)),Const.FILE_NAME2); |
| | | if (pwdHash != null) { |
| | | String pwdTrue = EncryptUtils.deAES(new String(pwdHash, Charset.forName("utf-8")), Const.AES_KEY.toCharArray()); |
| | | pwdTrue = pwdTrue.replace(" ","").replace(",","").replace("[","").replace("]",""); |
| | | pwd = pwdTrue.toCharArray(); |
| | | } |
| | | |
| | | //GO |
| | |
| | | } |
| | | return pwd; |
| | | } |
| | | |
| | | public static void main(String[] args) { |
| | | char[] chars = JarDecryptor.readPassFromJar(new File(JarUtils.getRootPath(null))); |
| | | } |
| | | } |
| | |
| | | //加密后文件存放位置 |
| | | private static final String ENCRYPT_PATH = "META-INF/" + Const.FILE_NAME + "/"; |
| | | |
| | | //加密后文件存放位置 |
| | | private static final String DESCRIPTION_PATH = "META-INF/"; |
| | | |
| | | /** |
| | | * 单例 |
| | | * |
| | |
| | | } |
| | | |
| | | /** |
| | | * 在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路径 |
| | |
| | | } |
| | | |
| | | /** |
| | | * 读取隐藏在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 配置文件路径 |
| | |
| | | |
| | | //加密后存储的位置 |
| | | File metaDir = new File(this.targetDir, "META-INF" + File.separator + Const.FILE_NAME); |
| | | File descriptionDir = new File(this.targetDir, "META-INF" + File.separator); |
| | | if (!metaDir.exists()) { |
| | | metaDir.mkdirs(); |
| | | } |
| | | |
| | | //无密码模式,自动生成一个密码 |
| | | if (this.password.length == 1 && this.password[0] == '#') { |
| | | /*if (this.password.length == 1 && this.password[0] == '#') { |
| | | char[] randChars = EncryptUtils.randChar(32); |
| | | this.password = EncryptUtils.md5(randChars); |
| | | File configPass = new File(metaDir, Const.CONFIG_PASS); |
| | | IoUtils.writeFile(configPass, StrUtils.toBytes(randChars)); |
| | | }*/ |
| | | |
| | | //密码文件生成 |
| | | if (this.password.length == 1 && this.password[0] == '#') { |
| | | char[] randChars2 = Const.FILE_NAME2_DESCRIPTION.replace(" ", "").toCharArray(); |
| | | //密码为混淆 原码+盐 |
| | | this.password = StrUtils.merger(randChars2, EncryptUtils.SALT); |
| | | String password2 = EncryptUtils.enAES(Arrays.toString(password), Const.AES_KEY.toCharArray()); |
| | | File configPass = new File(descriptionDir, Const.FILE_NAME2); |
| | | //将混淆后的密码加密后存储 |
| | | IoUtils.writeFile(configPass, password2.getBytes()); |
| | | } |
| | | |
| | | //有机器码 |
| | |
| | | */ |
| | | public class EncryptUtils { |
| | | //盐 |
| | | public static final char[] SALT = {'w', 'h', 'o', 'i', 's', 'y', 'o', 'u', 'r', 'd', 'a', 'd', 'd', 'y', '#', '$', '@', '#', '@'}; |
| | | public static final char[] SALT = {'i', 's', 'a', 'o', 'f', 'f', 'i', 'c', 'a', 'l', 'p', 'r', 'o', 'j','e','c','t', '#', '$', '@', '#', '@'}; |
| | | //rsa 长度 |
| | | private static int KEY_LENGTH = 1024; |
| | | |