001package top.cenze.utils.crypt; 002 003import cn.hutool.core.util.StrUtil; 004import lombok.SneakyThrows; 005import org.apache.commons.codec.binary.Base64; 006import top.cenze.utils.pojo.AppidSecret; 007 008import javax.crypto.Cipher; 009import javax.crypto.KeyGenerator; 010import javax.crypto.SecretKey; 011import javax.crypto.spec.IvParameterSpec; 012import javax.crypto.spec.SecretKeySpec; 013import java.util.UUID; 014 015/** 016 * AES对称加密工具 017 * 密钥加密/解密 018 * @author chengze 019 * @date 2023-11-14 22:05 020 */ 021public class AESUtil { 022 public static String AES = "AES";//指定算法类型 023 public static int KEY_LEN = 128;//指定密钥长度 024 public static String UTF_8 = "UTF-8";//编码格式 025 026 // CBC模式 027 private static final String key = "aesQiuChengZeKey"; // 必需为16位 028 private static final String initVector = "aesQiuChengZeVec"; // 必需为16位 029 030 /* 031 * @Author boy 032 * @Description 生成AES密钥 033 * @Date 2019/8/22 10:49 AM 034 * @Param [] 035 * @return java.lang.String 036 */ 037 public static String genAESKey() throws Exception{ 038 //构造密钥生成器,指定为AES算法 039 KeyGenerator keyGenerator = KeyGenerator.getInstance(AES); 040 //生成一个指定位数的随机源,KEY_LEN=128就是128位 041 keyGenerator.init(KEY_LEN); 042 //生成对称密钥 043 SecretKey sKey = keyGenerator.generateKey(); 044 return Base64.encodeBase64String(sKey.getEncoded()); 045 } 046 047 public static String encrypt(String data) throws Exception { 048 return encrypt(key, data); 049 } 050 051 /* 052 * @Author boy 053 * @Description 使用AES密钥加密数据 054 * @Date 2019/8/22 10:51 AM 055 * @Param [key, data] 056 * @return java.lang.String 057 */ 058 public static String encrypt(String key, String data) throws Exception { 059 if (StrUtil.isEmpty(key) || key.length() != 16) { 060 throw new RuntimeException("无效的密钥key"); 061 } 062 063 //获取key 064 IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8")); 065 SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), AES); 066 //根据指定算法生成密码器 067 Cipher cipher=Cipher.getInstance("AES/CBC/PKCS5PADDING"); 068 //初始化密码器,第一个参数为加密或者解密解密操作,第二个参数为使用的KEY 069 cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); 070 //将加密内容转化为字节数组 071 byte [] byte_data=data.getBytes(UTF_8); 072 //将字节数组加密 073 byte [] AES_data=cipher.doFinal(byte_data); 074 return Base64.encodeBase64String(AES_data); 075 } 076 077 public static String decrypt(String data) throws Exception { 078 return decrypt(key, data); 079 } 080 081 /* 082 * @Author boy 083 * @Description 使用AES密钥解密数据 084 * @Date 2019/8/22 8:06 PM 085 * @Param [key, data] 086 * @return java.lang.String 087 */ 088 public static String decrypt(String key, String data) throws Exception { 089 if (StrUtil.isEmpty(key) || key.length() != 16) { 090 throw new RuntimeException("无效的密钥key"); 091 } 092 093 //获取key 094 IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8")); 095 SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), AES); 096 //根据指定算法生成密码器 097 Cipher cipher=Cipher.getInstance("AES/CBC/PKCS5PADDING"); 098 //初始化密码器,第一个参数为加密或者解密解密操作,第二个参数为使用的KEY 099 cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); 100 //将加密内容转化为字节数组,因为数据是用Base64转换过的,所以需要使用base64解密 101 byte [] dataByte = Base64.decodeBase64(data.getBytes(UTF_8)); 102 //解密字节数组 103 byte [] decryptData=cipher.doFinal(dataByte); 104 return new String(decryptData); 105 } 106 107 @SneakyThrows 108 public static AppidSecret genAppidSecret() { 109 AppidSecret appidSecret = new AppidSecret(); 110 111 UUID uuid = UUID.randomUUID(); 112 String str = uuid.toString(); 113 // 将UUID的字符串形式中的破折号去掉 114 appidSecret.setAppId(str.replace("-", "")); 115 appidSecret.setSecret(encrypt(key, appidSecret.getAppId())); 116 117 return appidSecret; 118 } 119 120// private static final String key = "aeswwwLkd56InKey"; // 必需为16位 121// private static final String initVector = "aeswwwLkd56InVec"; // 必需为16位 122// 123// //加密 124// public static String encrypt(String value) { 125// try { 126// IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8")); 127// SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES"); 128// 129// Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); 130// cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); 131// 132// byte[] encrypted = cipher.doFinal(value.getBytes()); 133// return Base64.encodeBase64String(encrypted); 134// } catch (Exception ex) { 135// ex.printStackTrace(); 136// } 137// 138// return null; 139// } 140// 141// // 解密 142// public static String decrypt(String encrypted) { 143// try { 144// IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8")); 145// SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES"); 146// Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); 147// cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); 148// byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted)); 149// return new String(original); 150// } catch (Exception ex) { 151// ex.printStackTrace(); 152// } 153// 154// return null; 155// } 156}