package com.zsElectric.boot.common.util; import com.esotericsoftware.minlog.Log; import com.zsElectric.boot.common.constant.ConnectivityConstants; import lombok.extern.slf4j.Slf4j; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.util.Base64; import static com.zsElectric.boot.common.constant.ConnectivityConstants.*; /** * AES加解密工具类 * 支持AES-128-CBC-PKCS5Padding对称加解密算法 * @version 1.0 */ @Slf4j public class AESCryptoUtils { // 加密算法/模式/填充方式 private static final String ALGORITHM = "AES/CBC/PKCS5Padding"; private static final String AES = "AES"; private static final int IV_SIZE = 16; // 16字节 /** * AES加密 * @param data 待加密的明文 * @param key 密钥(必须为16字节) * @param iv 初始化向量(必须为16字节) * @return Base64编码的加密结果 * @throws Exception 加密异常 */ public static String encrypt(String data, String key, String iv) throws Exception { log.info("待加密数据:{}", data); // 参数校验 if (data == null || data.isEmpty()) { throw new IllegalArgumentException("加密数据不能为空"); } if (key == null || key.length() != 16) { throw new IllegalArgumentException("密钥必须为16位字符"); } if (iv == null || iv.length() != IV_SIZE) { throw new IllegalArgumentException("初始化向量必须为16位字符"); } try { // 创建密钥规范 SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), AES); // 创建初始化向量规范 IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8)); // 获取加密实例并初始化 Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); // 执行加密 byte[] encryptedBytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8)); // 返回Base64编码的加密结果 return Base64.getEncoder().encodeToString(encryptedBytes); } catch (Exception e) { throw new Exception("AES加密失败: " + e.getMessage(), e); } } /** * AES解密 * @param encryptedData Base64编码的加密数据 * @param key 密钥(必须为16字节) * @param iv 初始化向量(必须为16字节) * @return 解密后的明文 * @throws Exception 解密异常 */ public static String decrypt(String encryptedData, String key, String iv) throws Exception { // 参数校验 if (encryptedData == null || encryptedData.isEmpty()) { throw new IllegalArgumentException("解密数据不能为空"); } if (key == null || key.length() != 16) { throw new IllegalArgumentException("密钥必须为16位字符"); } if (iv == null || iv.length() != 16) { throw new IllegalArgumentException("初始化向量必须为16位字符"); } try { // 创建密钥规范 SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), AES); // 创建初始化向量规范 IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8)); // 获取解密实例并初始化 Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); // Base64解码并执行解密 byte[] encryptedBytes = Base64.getDecoder().decode(encryptedData); byte[] decryptedBytes = cipher.doFinal(encryptedBytes); // 返回解密结果 return new String(decryptedBytes, StandardCharsets.UTF_8); } catch (Exception e) { throw new Exception("AES解密失败: " + e.getMessage(), e); } } /** * 生成随机密钥(16字节) * @return 16字节的随机密钥 */ public static String generateRandomKey() { return generateRandomString(16); } /** * 生成随机初始化向量(16字节) * @return 16字节的随机IV */ public static String generateRandomIV() { return generateRandomString(16); } /** * 生成指定长度的随机字符串 * @param length 字符串长度 * @return 随机字符串 */ private static String generateRandomString(int length) { String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; StringBuilder sb = new StringBuilder(length); for (int i = 0; i < length; i++) { int index = (int) (characters.length() * Math.random()); sb.append(characters.charAt(index)); } return sb.toString(); } /** * 测试方法 */ public static void main(String[] args) throws Exception { try { // 测试数据 String originalData = "{\"OperatorID\":\"MA6DP6BE7\", \"OperatorSecret\":\"Sov2Gs590CLUbx4g\"}"; String key = DATA_SECRET; // 16字节密钥 String iv = DATA_SECRET_IV; // 16字节初始化向量 System.out.println("=== AES-128-CBC-PKCS5Padding 加解密测试 ==="); System.out.println("原始数据: " + originalData); System.out.println("密钥: " + key); System.out.println("初始化向量: " + iv); // 加密 long startTime = System.currentTimeMillis(); String encryptedData = encrypt(originalData, key, iv); long encryptTime = System.currentTimeMillis() - startTime; System.out.println("加密结果: " + encryptedData); System.out.println("加密耗时: " + encryptTime + "ms"); // 解密 startTime = System.currentTimeMillis(); String decryptedData = decrypt(encryptedData, key, iv); long decryptTime = System.currentTimeMillis() - startTime; System.out.println("解密结果: " + decryptedData); System.out.println("解密耗时: " + decryptTime + "ms"); // 验证加解密一致性 boolean isSuccess = originalData.equals(decryptedData); System.out.println("加解密验证: " + (isSuccess ? "成功" : "失败")); // 测试随机密钥生成 System.out.println("\n=== 随机密钥生成测试 ==="); String randomKey = generateRandomKey(); String randomIV = generateRandomIV(); System.out.println("随机密钥: " + randomKey); System.out.println("随机IV: " + randomIV); // 使用随机密钥进行加解密测试 String testEncrypted = encrypt("测试数据", randomKey, randomIV); String testDecrypted = decrypt(testEncrypted, randomKey, randomIV); System.out.println("随机密钥加解密测试: " + ("测试数据".equals(testDecrypted) ? "成功" : "失败")); } catch (Exception e) { e.printStackTrace(); } } }