import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.security.SecureRandom; import java.util.Arrays; import java.util.Base64; import java.util.Random; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; public class HybridEncryption { private static final String BASE_ALGORITHM = "AES/GCM/NoPadding"; private static final int GCM_TAG_LENGTH = 128; private static final int SALT_LENGTH = 16; private static final int IV_LENGTH = 12; // ==================== 核心加密方法 ==================== /** * 混合加密:标准AES-GCM + 自定义混淆 */ public static String hybridEncrypt(String plainText, String password) throws Exception { // 第一阶段:标准加密保证安全性 byte[] standardCipher = performStandardEncryption(plainText, password); // 第二阶段:自定义混淆增加隐蔽性 byte[] obfuscated = customObfuscation(standardCipher); // 第三阶段:格式化为可传输的字符串 return formatOutput(obfuscated); } /** * 混合解密 */ public static String hybridDecrypt(String encryptedData, String password) throws Exception { // 反向执行混淆层 byte[] obfuscated = parseInput(encryptedData); byte[] standardCipher = reverseCustomObfuscation(obfuscated); // 执行标准解密 return performStandardDecryption(standardCipher, password); } // ==================== 标准加密层 ==================== private static byte[] performStandardEncryption(String plainText, String password) throws Exception { // 生成随机盐和IV byte[] salt = generateRandomBytes(SALT_LENGTH); byte[] iv = generateRandomBytes(IV_LENGTH); // 从密码派生密钥 SecretKey secretKey = deriveKeyFromPassword(password, salt); // 标准AES-GCM加密 Cipher cipher = Cipher.getInstance(BASE_ALGORITHM); GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, iv); cipher.init(Cipher.ENCRYPT_MODE, secretKey, spec); byte[] cipherText = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8)); // 组合:salt + iv + ciphertext ByteBuffer buffer = ByteBuffer.allocate(salt.length + iv.length + cipherText.length); buffer.put(salt); buffer.put(iv); buffer.put(cipherText); return buffer.array(); } private static String performStandardDecryption(byte[] encryptedData, String password) throws Exception { ByteBuffer buffer = ByteBuffer.wrap(encryptedData); byte[] salt = new byte[SALT_LENGTH]; byte[] iv = new byte[IV_LENGTH]; buffer.get(salt); buffer.get(iv); byte[] cipherText = new byte[buffer.remaining()]; buffer.get(cipherText); // 派生密钥 SecretKey secretKey = deriveKeyFromPassword(password, salt); // 解密 Cipher cipher = Cipher.getInstance(BASE_ALGORITHM); GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, iv); cipher.init(Cipher.DECRYPT_MODE, secretKey, spec); byte[] plainText = cipher.doFinal(cipherText); return new String(plainText, StandardCharsets.UTF_8); } // ==================== 自定义混淆层 ==================== /** * 自定义混淆:可逆变换,不破坏安全性 */ private static byte[] customObfuscation(byte[] data) { if (data.length == 0) return data; // 1. 字节重排(基于伪随机序列) byte[] rearranged = rearrangeBytes(data); // 2. 添加伪装头部(看起来像其他协议) byte[] withHeader = addCamouflageHeader(rearranged); // 3. 可逆的数值变换 byte[] transformed = applyValueTransformation(withHeader); return transformed; } private static byte[] reverseCustomObfuscation(byte[] data) { if (data.length == 0) return data; // 反向执行混淆步骤 byte[] reversedTransform = reverseValueTransformation(data); byte[] withoutHeader = removeCamouflageHeader(reversedTransform); byte[] originalOrder = restoreByteOrder(withoutHeader); return originalOrder; } // --- 具体的混淆技术 --- private static byte[] rearrangeBytes(byte[] data) { // 使用基于数据的伪随机重排 byte[] seed = Arrays.copyOf(data, Math.min(8, data.length)); Random random = new Random(Arrays.hashCode(seed)); byte[] result = Arrays.copyOf(data, data.length); for (int i = 0; i < result.length; i++) { int j = random.nextInt(result.length); // 交换字节 byte temp = result[i]; result[i] = result[j]; result[j] = temp; } return result; } private static byte[] restoreByteOrder(byte[] data) { // 由于重排是随机的,我们需要在混淆时记录顺序信息 // 这里简化处理:实际使用时需要更复杂的方案 return data; // 在实际方案中需要记录置换映射 } private static byte[] addCamouflageHeader(byte[] data) { // 添加看起来像HTTP或其他协议的头部 String fakeHeader = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n"; byte[] headerBytes = fakeHeader.getBytes(StandardCharsets.US_ASCII); byte[] result = new byte[headerBytes.length + data.length]; System.arraycopy(headerBytes, 0, result, 0, headerBytes.length); System.arraycopy(data, 0, result, headerBytes.length, data.length); return result; } private static byte[] removeCamouflageHeader(byte[] data) { // 查找并移除伪装头部 String fakeHeader = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n"; byte[] headerBytes = fakeHeader.getBytes(StandardCharsets.US_ASCII); if (data.length < headerBytes.length) return data; // 验证头部 for (int i = 0; i < headerBytes.length; i++) { if (data[i] != headerBytes[i]) { return data; // 不是我们的格式,直接返回 } } byte[] result = new byte[data.length - headerBytes.length]; System.arraycopy(data, headerBytes.length, result, 0, result.length); return result; } private static byte[] applyValueTransformation(byte[] data) { // 可逆的数值变换:加法模256 byte[] result = new byte[data.length]; for (int i = 0; i < data.length; i++) { result[i] = (byte) ((data[i] + 137) % 256 - 128); // 简单的仿射变换 } return result; } private static byte[] reverseValueTransformation(byte[] data) { // 逆变换 byte[] result = new byte[data.length]; for (int i = 0; i < data.length; i++) { result[i] = (byte) ((data[i] + 128 + 119) % 256); // 逆变换参数 } return result; } // ==================== 辅助方法 ==================== private static SecretKey deriveKeyFromPassword(String password, byte[] salt) throws Exception { PBEKeySpec spec = new PBEKeySpec( password.toCharArray(), salt, 100000, 256); SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); byte[] keyBytes = factory.generateSecret(spec).getEncoded(); return new SecretKeySpec(keyBytes, "AES"); } private static byte[] generateRandomBytes(int length) { byte[] bytes = new byte[length]; new SecureRandom().nextBytes(bytes); return bytes; } private static String formatOutput(byte[] data) { // 使用Base64编码,但可以添加自定义分隔符 String base64 = Base64.getEncoder().encodeToString(data); return "ENC[" + base64.replace("=", "!") + "]"; } private static byte[] parseInput(String input) { if (!input.startsWith("ENC[") || !input.endsWith("]")) { throw new IllegalArgumentException("Invalid format"); } String base64 = input.substring(4, input.length() - 1).replace("!", "="); return Base64.getDecoder().decode(base64); } }