package com.mortals.xhx.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;

/**
 * 自定义编码、解码
 */
//加密过程：原文->base64->aes(1234567812345678)->des(12345678)->倒序（9位）->base64
//解密：base64->倒序(9位)->des(12345678)->aes(1234567812345678)->base64->原文
@Slf4j
public class EncryptUtil {
    public static final String ALGORITHM = "AES/ECB/PKCS5Padding";

    /**
     * 字符串转换为Base64
     *
     * @param text
     * @return
     */
    public static String toBase64(String text) {
        Base64 base64 = new Base64();
        try {
            return base64.encodeToString(text.getBytes("utf-8")).trim().replace("\n", "");
        } catch (UnsupportedEncodingException e) {
            log.error("字符串转换为Base64[{}]异常", e);
        }
        return null;
    }

    /**
     * Base64转换为字符串
     *
     * @param text
     * @return
     */
    private static String base64ToString(String text) {
        Base64 base64 = new Base64();
        try {
            return new String(base64.decode(text.getBytes("utf-8")), "UTF-8").trim().replace("\n", "");
        } catch (UnsupportedEncodingException e) {
            log.error("Base64转换为字符串[{}]异常", e);
        }
        return null;
    }


    /**
     * AES加密+Base64转码
     *
     * @param data 明文（16进制）
     * @param key  密钥
     * @return
     */
    public static String encrypt(String data, String key) {
        try {
            byte[] keys = key.getBytes("utf-8");
            // 明文
            SecretKeySpec sKeySpec = new SecretKeySpec(keys, "AES");
            //Cipher cipher = Cipher.getInstance(ALGORITHM, "BC");
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, sKeySpec);
            byte[] bjiamihou = cipher.doFinal(data.getBytes("utf-8"));
            // byte加密后,密文用base64加密;
            String miKey = Base64.encodeBase64String(bjiamihou);
            return miKey;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("AES加密[{}]异常", e);
        }
        return null;
    }

    /**
     * Base64解码 + AES解码
     *
     * @param data 密文 （16进制）
     * @param key  密钥
     * @return
     */
    public static String decrypt(String data, String key) {
        try {
            byte[] keys = key.getBytes("utf-8");
            byte[] datas = Base64.decodeBase64(data);
            SecretKeySpec sKeySpec = new SecretKeySpec(keys, "AES");
            //Cipher cipher = Cipher.getInstance(ALGORITHM, "BC");
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, sKeySpec);
            byte[] bjiemihou = cipher.doFinal(datas);
            // byte加密后
            String miKey = new String(bjiemihou, "utf-8");
            return miKey;
        } catch (Exception e) {
            log.error("AES解码[{}]异常", e);
        }
        return null;
    }

    /**
     * 转化为String
     *
     * @param buf
     * @return
     */
    private static String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    /**
     * 将16进制转换为二进制
     *
     * @param hexStr
     * @return
     */
    private static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }


    /**
     * DES加密（使用DES算法）
     *
     * @param message 需要加密的文本
     * @param key     密钥
     * @return 成功加密的文本
     */
    public static String toDesString(String key, String message) throws Exception {
        try {
            Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
            IvParameterSpec iv = new IvParameterSpec(key.getBytes("UTF-8"));
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
            return parseByte2HexStr(cipher.doFinal(message.getBytes("UTF-8")));
        } catch (Exception e) {
            log.error("DES加密[{}]异常", e);
        }
        return null;
    }

    /**
     * DES解密（使用DES算法）
     *
     * @param message 需要解密的文本
     * @param key     密钥
     * @return 成功加密的文本
     */
    public static String desToString(String key, String message) throws Exception {
        try {
            byte[] bytesrc = parseHexStr2Byte(message);//convertHexString(message);
            Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
            IvParameterSpec iv = new IvParameterSpec(key.getBytes("UTF-8"));
            cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
            byte[] retByte = cipher.doFinal(bytesrc);
            return new String(retByte);
        } catch (Exception e) {
            log.error("DES解密[{}]异常", e);
        }
        return null;
    }

    public static byte[] convertHexString(String ss) {
        byte digest[] = new byte[ss.length() / 2];
        for (int i = 0; i < digest.length; i++) {
            String byteString = ss.substring(2 * i, 2 * i + 2);
            int byteValue = Integer.parseInt(byteString, 16);
            digest[i] = (byte) byteValue;
        }
        return digest;
    }

    public static String toHexString(byte b[]) {
        StringBuffer hexString = new StringBuffer();
        for (int i = 0; i < b.length; i++) {
            String plainText = Integer.toHexString(0xff & b[i]);
            if (plainText.length() < 2)
                plainText = "0" + plainText;
            hexString.append(plainText);
        }
        return hexString.toString();
    }


    /**
     * 倒序处理，每orderNum位进行倒序排列
     *
     * @param sourceString 为需要加密的串
     * @param orderNum     为每x位进行倒序排列
     * @return
     */
    public static String toReverseString(int orderNum, String sourceString) {
        String csFive = "", encrypted2 = "";
        for (int i = 0; i < sourceString.length(); i++) {
            csFive = csFive + sourceString.charAt(i);
            if ((i + 1) % orderNum == 0 || (i + 1) >= sourceString.length()) {
                String csFive2 = "";
                for (int j = 0; j < csFive.length(); j++) {
                    csFive2 = csFive2 + csFive.charAt(csFive.length() - 1 - j);
                }
                encrypted2 += csFive2;
                csFive = "";
            }
        }
        return encrypted2;
    }

    /**
     * 加密
     *
     * @return
     */
    public static String myEnscrt(String sourceString, int orderNum, String desKey, String aesKey) throws Exception {
        //加密过程：原文->base64->aes(1234567812345678)->des(12345678)->倒序（9位）->base64
        String base64String = toBase64(sourceString);
        String aesString = encrypt(base64String, aesKey);
        //System.out.println("aseString==="+aesString);
        String desString = toDesString(desKey, aesString);
        String reverseString = toReverseString(orderNum, desString);
        String result = toBase64(reverseString);
        return result;
    }

    /**
     * 解密
     *
     * @return
     */
    public static String myReEnscrt(String targetString, int orderNum, String desKey, String aesKey) throws Exception {
        //解密：base64->倒序(9位)->des(12345678)->aes(1234567812345678)->base64->原文
        String reverseString = base64ToString(targetString);
        //System.out.println("reverseString"+reverseString);
        String desString = toReverseString(orderNum, reverseString);
        //System.out.println("desString"+desString);
        String aesString = desToString(desKey, desString);
       // System.out.println("aesString"+aesString);
        String base64String = decrypt(aesString, aesKey);
       // System.out.println("base64String"+base64String);
        String result = base64ToString(base64String);
        return result;
    }

    public static void main(String[] args) {
        try {
            String s = EncryptUtil.myEnscrt("7E:20:F5:32:60:6A", 9, "FZV1D&tr", "w4*KbUamPdZDnDpG");
            System.out.println("a===="+ s);
            String sa = EncryptUtil.myReEnscrt(s, 9, "FZV1D&tr", "w4*KbUamPdZDnDpG");
            System.out.println("sa===="+sa);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
