package com.friday.custody.service.trustService.haitong.utils;

import com.alibaba.fastjson.JSON;
import org.springframework.util.Base64Utils;

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 加密工具类
 *
 * @author zhangxiang
 * @date
 */
public class CipherUtil {
    private static final String ALGORITHM_RSA = "RSA";

    /**
     *
     * 加密
     * @param publicKey  公钥Key
     * @param data json字符串格式的data
     * @return data经过rsa加密后，以Base64编码的数据
     */
    public static String rsaEncryptToBase64(String publicKey, String data) throws Exception {
        return rsaEncryptToBase64(getPublicKey(publicKey), data);
    }


    /**
     *
     * 解密
     * @param privateKey  私钥Key
     * @param data 以Base64编码的经过rsa加密后的数据
     * @return data经过rsa解密后的json字符串数据
     */
    public static String rsaDecryptFromBase64(String privateKey, String data) throws Exception {
        return rsaDecryptFromBase64(getPrivateKey(privateKey), data);
    }


    /**
     * 测试实例
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        //公钥
        String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCKJlOlGagKYjRxt+bDiFT2ReFIetJT9lGWjvokqUh7mnrKHRvJL39Bdy9FBiCkSHDuqg1lja5o69ZY4IQf3CSTbrMYcUsiOWad/tfoHLPjH4steGsPX+0agYagMriQF7O01mIhD80ynhmmp9pTVTxj+A12c0636pMVIFKdxIRLwwIDAQAB";
        //私钥
        String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAIomU6UZqApiNHG35sOIVPZF4Uh60lP2UZaO+iSpSHuaesodG8kvf0F3L0UGIKRIcO6qDWWNrmjr1ljghB/cJJNusxhxSyI5Zp3+1+gcs+Mfiy14aw9f7RqBhqAyuJAXs7TWYiEPzTKeGaan2lNVPGP4DXZzTrfqkxUgUp3EhEvDAgMBAAECgYAH4KGaY3kihnEJHvxon+iAVoG/GUnPAderJyH6XzDD444m4jwIX8341Kv8WpoX5A2UflvfM5IDZ5dEYCEIlAv9yiO8mfZrJOpuiioPACKdKBEk2VlcUd7PcGQ/GLbvVCiODaKV8dzMvRgksMBTRDAAJT+1XjfvOBMWP2uoX5L0GQJBAO2ijAhMbrLO9P9qfK5LhVFYwGRJ2LyHLAzIHH5wcwuIe3k85/+RBccalD9CHkY9LNQNFgbMmc1GdyWyFKyA3ccCQQCU04duEBgRIwjuZbxj0OI+7ykoQW7dRneE3T1I3XMVFRUuPqquXDGkcspH6sDor1EWLHN5F6HY6UOWV+9sUdIlAkATVlfY0QdtC4RKSIsOz9xway10u8GkTcea3qna7CGgfaG2kus6E74JnrMTlrjJ9G5ybwIs2XdmieZmLeCazP2/AkEAhy2nGoKFybL/3sILnsJRbgZ/ZLAiSdxCnSzzCGcUq7aNmYaUM3FMKemV8EK7W946EaDodbnQaRxfJoTS1Jlw/QJBALYWFpmErv/WFKuSvt0zhHREtAmzvVgAR6AEEWAcQZ7QSRppyURrmwYlbxRvvOzh6WuGravI0BtsP4dyspusB88=";
        //需加密的参数
//        String data = "name = zhangsan";

        String license ="91310120332386472R";
        String clientId = "e7QEroOn";
//       String  appSigned= "bizParam=XXXX&businessLicense=XXXX&clientid=XXXX&timeStamp=XXX"
        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String timeStamp = format.format(date);
        String json0 = getJson0();

        String appSecret = "4fd06f5d5bf2836c50603d369ca05670a46ad4fdd8b658c7e9da4568c3409c84";

        //加密
        String rsaEncryptToBase64 = rsaEncryptToBase64(publicKey, json0);
        //解密
        String rsaDecryptFromBase64 = rsaDecryptFromBase64(privateKey, rsaEncryptToBase64);

        String  appSigned= "bizParam="+rsaEncryptToBase64+"&businessLicense="+license+"&clientid="+clientId+"&timeStamp="+timeStamp;


        appSigned = SignatureUtil.sha256(appSigned,appSecret);

        System.err.println("appSigned  "+appSigned);

        System.out.println("加密后:" + rsaEncryptToBase64);
        System.out.println("解密后:" + rsaDecryptFromBase64);

        Map map = new HashMap();
        map.put("clientid",clientId);
        map.put("timeStamp",timeStamp);
        map.put("businessLicense",license);
        map.put("bizParam",rsaEncryptToBase64);
        map.put("appSigned",appSigned);
        String s = JSON.toJSONString(map);
        System.out.println(s);
    }

    private static String getJson0(){
        Map map = new HashMap<>();
//        map.put()
        return JSON.toJSONString(map);
    }

    private static String rsaEncryptToBase64(Key key, String data) {
        return Base64Utils.encodeToString(rsaEncrypt(key, data.getBytes()));
    }

    private static String rsaDecryptFromBase64(Key key, String data) {
        return new String(rsaDecrypt(key, Base64Utils.decodeFromString(data)));
    }

    private static byte[] rsaEncrypt(Key key, byte[] data) {
        return cipherData(ALGORITHM_RSA, Cipher.ENCRYPT_MODE, key, data);
    }

    private static byte[] rsaDecrypt(Key key, byte[] data) {
        return cipherData(ALGORITHM_RSA, Cipher.DECRYPT_MODE, key, data);
    }

    private static PublicKey getPublicKey(String key) throws Exception {
        byte[] keyBytes;
//        keyBytes = (new BASE64Decoder()).decodeBuffer(key);
        Base64.Decoder decoder = Base64.getDecoder();
        keyBytes = decoder.decode(key);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
    }

    private static PrivateKey getPrivateKey(String key) throws Exception {
        byte[] keyBytes;
//        keyBytes = (new BASE64Decoder()).decodeBuffer(key);
        Base64.Decoder decoder = Base64.getDecoder();
        keyBytes = decoder.decode(key);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }

    public static byte[] cipherData(String algorithm, int cipherMode, Key key, byte[] data) {
        try {
            /* Cipher对象实际完成加密或解密操作 */
            Cipher cipher = Cipher.getInstance(algorithm);
            /* 用密钥初始化Cipher对象 */
            cipher.init(cipherMode, key, new SecureRandom());
            // 处理数据
            if (cipherMode == Cipher.DECRYPT_MODE){
                byte[] inputArray = data;
                int inputLength = inputArray.length;
                // 最大加密字节数，超出最大字节数需要分组加密
                int MAX_ENCRYPT_BLOCK = 128;
                // 标识
                int offSet = 0;
                byte[] resultBytes = {};
                byte[] cache = {};
                while (inputLength - offSet > 0) {
                    if (inputLength - offSet > MAX_ENCRYPT_BLOCK) {
                        cache = cipher.doFinal(inputArray, offSet, MAX_ENCRYPT_BLOCK);
                        offSet += MAX_ENCRYPT_BLOCK;
                    } else {
                        cache = cipher.doFinal(inputArray, offSet, inputLength - offSet);
                        offSet = inputLength;
                    }
                    resultBytes = Arrays.copyOf(resultBytes, resultBytes.length + cache.length);
                    System.arraycopy(cache, 0, resultBytes, resultBytes.length - cache.length, cache.length);
                }
                return resultBytes;
            } else if (cipherMode == Cipher.ENCRYPT_MODE){
                // 对数据加密
                byte[] inputArray = data;
                int inputLength = inputArray.length;
                // 最大加密字节数，超出最大字节数需要分组加密
                int MAX_ENCRYPT_BLOCK = 117;
                // 标识
                int offSet = 0;
                byte[] resultBytes = {};
                byte[] cache = {};
                while (inputLength - offSet > 0) {
                    if (inputLength - offSet > MAX_ENCRYPT_BLOCK) {
                        cache = cipher.doFinal(inputArray, offSet, MAX_ENCRYPT_BLOCK);
                        offSet += MAX_ENCRYPT_BLOCK;
                    } else {
                        cache = cipher.doFinal(inputArray, offSet, inputLength - offSet);
                        offSet = inputLength;
                    }
                    resultBytes = Arrays.copyOf(resultBytes, resultBytes.length + cache.length);
                    System.arraycopy(cache, 0, resultBytes, resultBytes.length - cache.length, cache.length);
                }
                return resultBytes;
            }
            return null;
        } catch (Exception e) {
            throw new RuntimeException("数据加解密出错！");
        }
    }
}
