package org.dromara.zjk.utils;

import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Base64Utils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.util.Random;

public class AesUtils {
    private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final Random RANDOM = new SecureRandom();

    /**
     * 获取长度为 6 的随机字母+数字
     * @return 随机数字
     */
    public static String getRandomNumber() {
        char[] nonceChars = new char[16];  //指定长度为6位/自己可以要求设置

        for (int index = 0; index < nonceChars.length; ++index) {
            nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
        }
        return new String(nonceChars);
    }

    /**
     * 编码
     */
    private static final String ENCODING = "UTF-8";
    /**
     * 算法定义
     */
    private static final String AES_ALGORITHM = "AES";
    /**
     * 指定填充方式
     */
    private static final String CIPHER_PADDING = "AES/ECB/PKCS5Padding";
    private static final String CIPHER_CBC_PADDING = "AES/CBC/PKCS5Padding";
    /**
     * 偏移量(CBC中使用，增强加密算法强度)
     */
    private static final String IV_SEED = "1234567812345678";

    /**
     * AES加密
     * @param content 待加密内容
     * @param aesKey  密码
     * @return
     */
    public static String encrypt(String content, String aesKey){
        if(StringUtils.isBlank(content)){
//            log.info("AES encrypt: the content is null!");
            return null;
        }
        //判断秘钥是否为16位
        if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){
            try {
                //对密码进行编码
                byte[] bytes = aesKey.getBytes(ENCODING);
                //设置加密算法，生成秘钥
                SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);
                // "算法/模式/补码方式"
                Cipher cipher = Cipher.getInstance(CIPHER_PADDING);
                //选择加密
                cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
                //根据待加密内容生成字节数组
                byte[] encrypted = cipher.doFinal(content.getBytes(ENCODING));
                //返回base64字符串
                return Base64Utils.encodeToString(encrypted);
            } catch (Exception e) {
//                log.info("AES encrypt exception:" + e.getMessage());
                throw new RuntimeException(e);
            }

        }else {
//            log.info("AES encrypt: the aesKey is null or error!");
            return null;
        }
    }

    /**
     * 解密
     *
     * @param content 待解密内容
     * @param aesKey  密码
     * @return
     */
    public static String decrypt(String content, String aesKey){
        if(StringUtils.isBlank(content)){
//            log.info("AES decrypt: the content is null!");
            return null;
        }
        //判断秘钥是否为16位
        if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){
            try {
                //对密码进行编码
                byte[] bytes = aesKey.getBytes(ENCODING);
                //设置解密算法，生成秘钥
                SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);
                // "算法/模式/补码方式"
                Cipher cipher = Cipher.getInstance(CIPHER_PADDING);
                //选择解密
                cipher.init(Cipher.DECRYPT_MODE, skeySpec);

                //先进行Base64解码
                byte[] decodeBase64 = Base64Utils.decodeFromString(content);

                //根据待解密内容进行解密
                byte[] decrypted = cipher.doFinal(decodeBase64);
                //将字节数组转成字符串
                return new String(decrypted, ENCODING);
            } catch (Exception e) {
//                log.info("AES decrypt exception:" + e.getMessage());
                throw new RuntimeException(e);
            }

        }else {
//            log.info("AES decrypt: the aesKey is null or error!");
            return null;
        }
    }

    /**
     * AES_CBC加密
     *
     * @param content 待加密内容
     * @param aesKey  密码
     * @return
     */
    public static String encryptCBC(String content, String aesKey){
        if(StringUtils.isBlank(content)){
//            log.info("AES_CBC encrypt: the content is null!");
            return null;
        }
        //判断秘钥是否为16位
        if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){
            try {
                //对密码进行编码
                byte[] bytes = aesKey.getBytes(ENCODING);
                //设置加密算法，生成秘钥
                SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);
                // "算法/模式/补码方式"
                Cipher cipher = Cipher.getInstance(CIPHER_CBC_PADDING);
                //偏移
                IvParameterSpec iv = new IvParameterSpec(IV_SEED.getBytes(ENCODING));
                //选择加密
                cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
                //根据待加密内容生成字节数组
                byte[] encrypted = cipher.doFinal(content.getBytes(ENCODING));
                //返回base64字符串
                return Base64Utils.encodeToString(encrypted);
            } catch (Exception e) {
//                log.info("AES_CBC encrypt exception:" + e.getMessage());
                throw new RuntimeException(e);
            }

        }else {
//            log.info("AES_CBC encrypt: the aesKey is null or error!");
            return null;
        }
    }

    /**
     * AES_CBC解密
     *
     * @param content 待解密内容
     * @param aesKey  密码
     * @return
     */
    public static String decryptCBC(String content, String aesKey){
        if(StringUtils.isBlank(content)){
//            log.info("AES_CBC decrypt: the content is null!");
            return null;
        }
        //判断秘钥是否为16位
        if(StringUtils.isNotBlank(aesKey) && aesKey.length() == 16){
            try {
                //对密码进行编码
                byte[] bytes = aesKey.getBytes(ENCODING);
                //设置解密算法，生成秘钥
                SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);
                //偏移
                IvParameterSpec iv = new IvParameterSpec(IV_SEED.getBytes(ENCODING));
                // "算法/模式/补码方式"
                Cipher cipher = Cipher.getInstance(CIPHER_CBC_PADDING);
                //选择解密
                cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

                //先进行Base64解码
                byte[] decodeBase64 = Base64Utils.decodeFromString(content);

                //根据待解密内容进行解密
                byte[] decrypted = cipher.doFinal(decodeBase64);
                //将字节数组转成字符串
                return new String(decrypted, ENCODING);
            } catch (Exception e) {
//                log.info("AES_CBC decrypt exception:" + e.getMessage());
                throw new RuntimeException(e);
            }

        }else {
//            log.info("AES_CBC decrypt: the aesKey is null or error!");
            return null;
        }
    }

    public static void main(String[] args) {
        String content="fx/cZTfDSwcPlU9Lgkud8WIe66mxnyHwO/OKG3WKfqRk0AcMGufIdvVZB4HT7ASPbXngSbZXABXzoHhC6kiUS7jE3EgyYqgLQoLO4+1az6cqjGaFT+GH3tZ87CCMM4nsN0O3FzD6h1jydUhHirkVLmqT76SO1czXEqIXxbNGl6YhzXV8k4oQXOZAnXnXwCZX5yYitsJKrxllHuCTEAsISWhWTx3BS5gDFA3Qr7rzJgJ9PFQrvzAw9G/5K3v6BSwEwhDradTJUkchzIgIGIg2PNlGN1Onajz6IAUk+WV7obgHCAy9DTXt+34Tu48xuGA4g7coNziI7GzAG3tCx2ldO2XaRDCTnRb+unRbXXU9q7iSx/Cz7z7oLvid9sOK7VHqzim8XXc6XoaVT6ShqsLK5xEum8+zc6m8CzM4CZy5WMAXIgXbLybaTZ0FmK8tqFFB2NGhrSa13RdNs7PMU5Wsl2b/Ml4g3d3uzgD1zVCeHg1GulGhxehvhYMbeVyOWCGjDw6zw8J3EjBXrQKFIeczMga4EQuXWIp3+hJZvs4YIsvRvK0u6/Bs2IK+cThyKADUMKCuGLPWrueEapZ3zcdWGRCtan6+0GM+pyQw1ko1YnfUhE5HLvSgeaMUZlCjT+D3H2ucwSRimkBGDh+M9qdudx5YZBLwj6rnNbHqVLxE9Dhs+2sVCxIJslChxD7eJkR2CrUBGejJOoXGglcjcOUSkuYclmguJSelEeGHy/AFwRFe5G+LUF/Hfr0Lt+dpA4RV9eg4smaq8yCyaYUs+sjJg6dI8MjTDPL7JWjo9ginMDMbgbj3ZNxtzFdUswq/Z5J/FJ3H1wzSyaXKo9XRN/yebTB30XTdePLWfnOron/KDW0uXHU/UMXHefc6yX970c8PbZR+rUxYl0ow53f78HS2+o8cPUNTowC9VLQvlHgpmuuT1QMBFrV22MyBgBE7pBdWhdytC0pj96P9Bb+JBeSouFAxdM9U1qs5c5e8/xn9p7cgviMrYzAVEXK4Hy4rKel0MtdqrJZaF32Qd9Ke8ZVaP2geaDhI/TRAGUiJ3HDzDwxteeBJtlcAFfOgeELqSJRLLhJCOwxl4L4e47Pv80esk6Tp41+P3CGG7j1ljPZYaE47c6FfWh4aD3BdjOv7K5qhx3ZF5sErxAgJI/YTJmi1PoSG6P4UlOkWdXSjVBod3qrUVNUksXruaCg2duoT7y0sHGZv0CpBWf0Z/zr/1RJNYg2YJQ4AqTOVeyANRJe162TkdMs1Jm814a9lvGB6z0hL3l/iZE4N+AFQGcqhyCrMMPtGa+HwAQU5Fd0GRxW4thgqHAvElGaHTBa0xTyPS71xXkm73MykIPeMHZQ6Bzma1mXaRDCTnRb+unRbXXU9q7iplJEujP5XfYRMg2yHv6upFJ3H1wzSyaXKo9XRN/yebcbr98MkDGjBVqf5ugl/paV/pTx2FimbVdKzRaFGE7G6pNcUylm2NeQGbOUl/zDYslbbpHxvP/XJKDE+Bn5OVvMLsDS3VlsBQ6Oh5J6hoRXIYtoA/7b0CjJtcvYMngn5P7kUwbmaRo+0zgOuCOVzA0gP/fKw1lSGyEJa+Nq5bEto";

        System.out.println( AesUtils.decrypt(content,"KlzY40Xw2wywV9Me"));
    }

}
