|
@@ -0,0 +1,95 @@
|
|
|
+package com.sqx.modules.utils;
|
|
|
+
|
|
|
+import lombok.val;
|
|
|
+
|
|
|
+import javax.crypto.Cipher;
|
|
|
+import javax.crypto.KeyGenerator;
|
|
|
+import javax.crypto.SecretKey;
|
|
|
+import javax.crypto.spec.IvParameterSpec;
|
|
|
+import javax.crypto.spec.SecretKeySpec;
|
|
|
+import java.security.SecureRandom;
|
|
|
+import java.util.Base64;
|
|
|
+
|
|
|
+public class AESCBCWithRandomIV {
|
|
|
+
|
|
|
+ private static final String AES = "AES";
|
|
|
+ private static final String AES_CBC_PADDING = "AES/CBC/PKCS5Padding";
|
|
|
+ private static final int IV_SIZE = 16; // 16 bytes for AES block size
|
|
|
+ private static final int KEY_SIZE = 128;
|
|
|
+
|
|
|
+ // ⚠️ 真实项目中,请从安全的配置中读取密钥,避免硬编码!
|
|
|
+ private static final String SECRET_KEY = "nihyMG%DJ0I0nhlA"; // 16 bytes = 128 bits
|
|
|
+
|
|
|
+ /**
|
|
|
+ * AES CBC 加密,随机生成 IV 并一起编码返回(IV + CipherText)
|
|
|
+ */
|
|
|
+ public static String encrypt(String plainText,String secretKey) throws Exception {
|
|
|
+ byte[] keyBytes = secretKey.getBytes("UTF-8");
|
|
|
+ SecretKeySpec keySpec = new SecretKeySpec(keyBytes, AES);
|
|
|
+
|
|
|
+ // 随机 IV
|
|
|
+ byte[] ivBytes = new byte[IV_SIZE];
|
|
|
+ new SecureRandom().nextBytes(ivBytes);
|
|
|
+ IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
|
|
|
+
|
|
|
+ Cipher cipher = Cipher.getInstance(AES_CBC_PADDING);
|
|
|
+ cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
|
|
|
+ byte[] encryptedBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
|
|
|
+
|
|
|
+ // 拼接 IV + 加密内容
|
|
|
+ byte[] combined = new byte[IV_SIZE + encryptedBytes.length];
|
|
|
+ System.arraycopy(ivBytes, 0, combined, 0, IV_SIZE);
|
|
|
+ System.arraycopy(encryptedBytes, 0, combined, IV_SIZE, encryptedBytes.length);
|
|
|
+
|
|
|
+ return Base64.getEncoder().encodeToString(combined);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * AES CBC 解密,从密文中提取 IV 解密
|
|
|
+ */
|
|
|
+ public static String decrypt(String base64CipherText,String secretKey) throws Exception {
|
|
|
+ byte[] combined = Base64.getDecoder().decode(base64CipherText);
|
|
|
+
|
|
|
+ byte[] ivBytes = new byte[IV_SIZE];
|
|
|
+ byte[] encryptedBytes = new byte[combined.length - IV_SIZE];
|
|
|
+
|
|
|
+ System.arraycopy(combined, 0, ivBytes, 0, IV_SIZE);
|
|
|
+ System.arraycopy(combined, IV_SIZE, encryptedBytes, 0, encryptedBytes.length);
|
|
|
+
|
|
|
+ IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
|
|
|
+ SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes("UTF-8"), AES);
|
|
|
+
|
|
|
+ Cipher cipher = Cipher.getInstance(AES_CBC_PADDING);
|
|
|
+ cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
|
|
|
+ byte[] decrypted = cipher.doFinal(encryptedBytes);
|
|
|
+
|
|
|
+ return new String(decrypted, "UTF-8");
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String getSecretKey(){
|
|
|
+ String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-=.$%^&*#";
|
|
|
+ SecureRandom random = new SecureRandom();
|
|
|
+ StringBuilder key = new StringBuilder(16);
|
|
|
+
|
|
|
+ for (int i = 0; i < 16; i++) {
|
|
|
+ key.append(chars.charAt(random.nextInt(chars.length())));
|
|
|
+ }
|
|
|
+ System.out.println("随机生成的密钥: " + key.toString());
|
|
|
+ return key.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 🔍 示例测试
|
|
|
+ public static void main(String[] args) throws Exception {
|
|
|
+ String text = "210421200001084233";
|
|
|
+ val key = getSecretKey();
|
|
|
+ String encrypted = encrypt(text,key);
|
|
|
+ String decrypted = decrypt(encrypted,key);
|
|
|
+
|
|
|
+
|
|
|
+ System.out.println("原文: " + text);
|
|
|
+ System.out.println("加密: " + encrypted);
|
|
|
+ System.out.println("解密: " + decrypted);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|