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}