package com.trs.project.util;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

@SuppressWarnings("unchecked")
public class RSAUtil {
    /** */
    /**
     * 获取私钥的key
     */
    private static final String PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIXX5mUam7SgTwxlmm1rFjJn+CaMs+TPHXNyEbRj04gQ4HHsA2vAkeGjnSr6Jg3cHkNJaraU1rk+tSPb7lCUxzvI4H3JGwnxeFCsPVthhJBd4lh9UvoR32D/qO4SaP2YpVVkIrE5gEJFcbUFMIV+HcQnbwfkwIqGea2kGtYOhAQTAgMBAAECgYA8TLa6GjDIQekbNrNKVJKdhwXfqEhr73vfRScA1HC6vo/AA4rPAuU2eRYYBLccS20+91aih4/tyXimfTFzEHRprRDipyAZQcVLhGdyE/HBdDZBvzLxPumnNJHpZ6FhS9N0UF4cA8CHFAfGkK4vM/Sfi84//Mo3FjCDCII71CpXEQJBAM8XdHJcvQ2dkxnNtGHjljZdwrReWyBcOTJKEKaGkWT3TWBrA70+4OUmQFdIjjBfy4WX+W9MYB9ifI4AFEV1IhcCQQClc+5W4CVfMZayZ2lOSZXkGZf5gN5BYCTIdBcQ0mjCCj9m7+AamwHKJunzPrAIS1YlhtcmhHMXWCyEU/pqnpdlAkAstBBz+2boAILXiBsPInSziavVCaU8KAxEuc48VEIgfG3ciV1GRcOAU7CB5uyirpsdXIAAsYjyXW0rrgKyN6XDAkEAmNcQfGaRf2+ys1m+ONjXQ6C0+IKoTiI/uIEtcZe9uEp5KWE8V7eLnq/1/IOTYAYgLYhzphxCqXUForRlJysb1QJAL0aFB/OLfA7b19h0As011vZuccYJ0Rnunf4a1k4VjfMCOkFRoZlr0LuOwhGqtXgQ2/NBgL2il7KKkzXdSZidbQ==";


    public static final String ENCRYPTION_ALGORITHM = "RSA";
    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
    public static final String ENCODING = "UTF-8";

    static MyPair<PublicKey, PrivateKey> pair;

    static {
        try {
            pair = genKeyPair();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }

    /**
     * RSA最大加密明文大小《规定》
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;

    /**
     * RSA最大解密密文大小《规定》
     */
    private static final int MAX_DECRYPT_BLOCK = 128;

    /**
     * 生成密钥
     */
    public static MyPair<PublicKey, PrivateKey> genKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ENCRYPTION_ALGORITHM);
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        return new MyPair(keyPair.getPublic(), keyPair.getPrivate());
    }

    /**
     * 取得公钥
     */
    public static String getPublicKey() {
        return Base64Util.encode(pair.getL().getEncoded()).toString().replaceAll("\\s", "");
    }

    /**
     * 取得私钥
     */
    public static String getPrivateKey() {
        return Base64Util.encode(pair.getR().getEncoded()).toString().replaceAll("\\s", "");
    }

    /**
     * 加密
     */
    public static String encrypt(String data, String keyString, boolean isPublic) throws Exception {
        MyPair<Key, KeyFactory> pair = generateKeyAndFactory(keyString, isPublic);
        KeyFactory keyFactory = pair.getR();
        Key key = pair.getL();
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] dataBytes = data.getBytes(ENCODING);
        int dataLen = dataBytes.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;

        while (dataLen - offSet > 0) {//对数据分段加密
            if (dataLen - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(dataBytes, offSet, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(dataBytes, offSet, dataLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        return Base64Util.encode(encryptedData).toString().replaceAll("\\s", "");
    }

    /**
     * 解密
     */
    public static String decrypt(String data, String keyString, boolean isPublic) throws Exception {

        MyPair<Key, KeyFactory> pair = generateKeyAndFactory(keyString, isPublic);
        KeyFactory keyFactory = pair.getR();
        Key key = pair.getL();
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, key);

        byte[] dataBytes = Base64Util.decode(data.getBytes(ENCODING));

        int inputLen = dataBytes.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        while (inputLen - offSet > 0) {//对数据分段解密
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(dataBytes, offSet, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(dataBytes, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        return new String(decryptedData, ENCODING);
    }

    /**
     * 解密2
     */
    public static String decrypt2(String data) throws Exception {

        MyPair<Key, KeyFactory> pair = generateKeyAndFactory(PRIVATE_KEY, false);
        KeyFactory keyFactory = pair.getR();
        Key key = pair.getL();
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, key);

        byte[] dataBytes = Base64Util.decode(data.getBytes(ENCODING));

        int inputLen = dataBytes.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        while (inputLen - offSet > 0) {//对数据分段解密
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(dataBytes, offSet, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(dataBytes, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        return new String(decryptedData, ENCODING);
    }

    /**
     * 生成钥匙
     */
    public static MyPair<Key, KeyFactory> generateKeyAndFactory(String keyString, boolean isPublic) throws Exception {
        byte[] keyBytes = Base64Util.decode(keyString.getBytes(ENCODING));
        KeyFactory keyFactory = KeyFactory.getInstance(ENCRYPTION_ALGORITHM);
        Key key;
        if (isPublic) {
            X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(keyBytes);
            key = keyFactory.generatePublic(encodedKeySpec);
        } else {
            PKCS8EncodedKeySpec encodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
            key = keyFactory.generatePrivate(encodedKeySpec);
        }
        return new MyPair(key, keyFactory);
    }

    /**
     * 对信息生成数字签名（用私钥）
     */
    public static String sign(byte[] data, String keyString) throws Exception {
        MyPair<Key, KeyFactory> pair = generateKeyAndFactory(keyString, false);
        Key key = pair.getL();
        PrivateKey privateKey = (PrivateKey) key;
        // 用私钥对信息生成数字签名
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(privateKey);
        signature.update(data);
        return Base64Util.encode(signature.sign()).toString();
    }

    /**
     * 校验数字签名（用公钥）
     */
    public static boolean verify(byte[] data, String keyString, String sign) throws Exception {
        MyPair<Key, KeyFactory> pair = generateKeyAndFactory(keyString, true);
        Key key = pair.getL();
        PublicKey publicKey = (PublicKey) key;
        // 取公钥匙对象
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(publicKey);
        signature.update(data);
        return signature.verify(Base64Util.decode(sign.getBytes(ENCODING)));
    }

    static class MyPair<T, K> {
        private T l;
        private K r;

        public MyPair(T l, K r) {
            this.l = l;
            this.r = r;
        }

        public T getL() {
            return l;
        }

        public K getR() {
            return r;
        }
    }

    public static void main(String[] args) throws Exception {
        /**
         * isPublick:公钥，true;私钥：false   客户端私钥加密，服务端公钥解密
         */

        String data = "[{\"attachmentCode\":\"\",\"zbXiangMuWenJian\":\"ff8080814203def601420853164800b4\",\"TENDER_AGENCY_ROLE\":\"\",\"tendererName\":\"--\",\"TENDERER_ROLE\":\"\",\"isShiShuGuoQi\":1,\"tendererCodeType\":\"--\",\"infoReporterName\":\"caigouceshi2\",\"suoShuQiYe\":1,\"tenderProjectName\":\"阳光采购平台接口测试\",\"PROJECT_GUID\":\"2c9791e4785dd570017862cdddfa0002\",\"projectCode\":\"CGLX-202103-007\",\"OWNER_NAME\":\"\",\"SUPERVISE_DEPT_NAME\":\"--\",\"tenderContent\":\"--\",\"approveDeptCode\":\"--\",\"TENDER_PROJECT_TYPE\":\"D03\",\"REGION_CODE\":\"440300\",\"tenderAgencyName\":\"--\",\"tenderMode\":\"1\",\"tenderProjectCode\":\"JT-ZB20210324-001\",\"version\":1617344867790,\"tendererCode\":\"--\",\"tendererType\":\"\",\"approveDeptName\":\"\",\"tenderOrganizeForm\":1,\"createTime\":1617344867790,\"isZhanLueYingJiWuZi\":0,\"superviseDeptCode\":\"\",\"tenderAgencyCode\":\"--\",\"tenderAgencyCodeType\":\"--\",\"platformCode\":\"--\",\"TENDER_PROJECT_GUID\":\"2c9791e4785dd570017862db6aff000d\"}]";
        String key = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJGxu3HKfsURPvE9MV2mWnOKiD82IUB8PDyyBUsjhWjtOdFvabOBzCDBdNeptP3JsVth52W5iYe2hTr3GufqWmnDVQ98jJmZhpCyefDQuBkAnDyrYU6OnLbw9fkfjWaN+69neuBwZ73awE8IwfwVsAEEQ1syGmeHLAcGPgy9m5prAgMBAAECgYAQLoxiLBp+atbx1lkYTLS5JobRdoKk9ed+2krqOIzFxatpTpWP4Xe5n6MJnQjEM1Wmj64yxzO2RhhwHyf24DmgX5OEvjwnee1E9DIJpWNEe1E5xP8qz1L032SbX9Ngo9yIZlUkfwLDjN8EChKwt4bz2N41epXEiDN/MK2hXDUmAQJBAPKR7ldH0zyTWh1oyrgNiXeClvNIa/wgaC6T9+ol+aeoXcPDfk77ZT8lcRPQCdHyHb9u/oDKrPCnyUhj5AFTSQECQQCZwrs7iN+cr7oQuUzxoYbT/JgZw/4Fvqp4MXGPe3Sp7t16lXxcmskX3+iBLRLt+Xy4biWWyOtej4RSK0JPPRdrAkAyVHEdjvuXUAOcooedVMG3GFN1uwsczySOtYj0/lgkn1yFJ+TnQmYpif1CXSIMe64McF1CH8tuS4IKER/X3o4BAkBi0NkPS8mZov2LHesrJsnFlwIRHPo1qvFXST9YHNk/FLnVvBguU3OFGmsMCXGu6rWSuYcCvqE1Jjq9q/tzfSl9AkEAm5wMHzPR7emI0OsZdM3a3Ci4vBSglPWAJKPyaETmwqh1BnSZIjaPJwUfWzGJm5A2UhdXTkLi+wXsFYM+8ZxS/Q==";
        String key1 = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJGxu3HKfsURPvE9MV2mWnOKiD82IUB8PDyyBUsjhWjtOdFvabOBzCDBdNeptP3JsVth52W5iYe2hTr3GufqWmnDVQ98jJmZhpCyefDQuBkAnDyrYU6OnLbw9fkfjWaN+69neuBwZ73awE8IwfwVsAEEQ1syGmeHLAcGPgy9m5prAgMBAAECgYAQLoxiLBp+atbx1lkYTLS5JobRdoKk9ed+2krqOIzFxatpTpWP4Xe5n6MJnQjEM1Wmj64yxzO2RhhwHyf24DmgX5OEvjwnee1E9DIJpWNEe1E5xP8qz1L032SbX9Ngo9yIZlUkfwLDjN8EChKwt4bz2N41epXEiDN/MK2hXDUmAQJBAPKR7ldH0zyTWh1oyrgNiXeClvNIa/wgaC6T9+ol+aeoXcPDfk77ZT8lcRPQCdHyHb9u/oDKrPCnyUhj5AFTSQECQQCZwrs7iN+cr7oQuUzxoYbT/JgZw/4Fvqp4MXGPe3Sp7t16lXxcmskX3+iBLRLt+Xy4biWWyOtej4RSK0JPPRdrAkAyVHEdjvuXUAOcooedVMG3GFN1uwsczySOtYj0/lgkn1yFJ+TnQmYpif1CXSIMe64McF1CH8tuS4IKER/X3o4BAkBi0NkPS8mZov2LHesrJsnFlwIRHPo1qvFXST9YHNk/FLnVvBguU3OFGmsMCXGu6rWSuYcCvqE1Jjq9q/tzfSl9AkEAm5wMHzPR7emI0OsZdM3a3Ci4vBSglPWAJKPyaETmwqh1BnSZIjaPJwUfWzGJm5A2UhdXTkLi+wXsFYM+8ZxS/Q==";
        //加密
        String encryptStr = encrypt(data, key, false);
        System.out.println(encryptStr);

        //解密
        /*String decrypt = decrypt("YEBDCY+4Ab7vM6v/Ol1HTCowbEsPhFqgH929NU4oC1ZEdI8cO0kfgdhYj4DaR5VnZRW1peChr5WiovuHNa8fy6fLvW1Ya1oL6bTxeUphgRmOB1TEeyi2E2Aud5Hd1vC6nxcD73C61vQ/nA9KFXfTlCWek/IksWIEu8sG8GacSYBbZ1E0/gTj1v2lrqfaO7oZIqYMc36oKm4kRZ9p1TicvMetU3Dqi5HEP9eQ4mitTyjfxNPHHVJ23La7Uy5wh3xcX5k2uXMzdkYhX+x/3lNhxwz15IB9EacRgbYPvTqj7SpX95lDnAB5XxD61A99CdxvQTjYXSCDUOmT986meQQ9jCuPBhIRd5bvbgOfleP/aFunjQNjlKEqJtqboRFNXuvd2GrXhxauLutE1UQ5TrtC5Fupq6IPRhdqeZYcj1UpeCsywDEwcM8rgwMnkJ+dm5FgSSZNqlSnHn5XoqMHEeFqemQEGMgxDy1dVHD7+R1Yt7Z0zKFemppW6/XreBuALelV", "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIQsl/sknxHr26sJQsU+e+OLXouCjOoGvbTfiUKi4XKHqSpXGO4vPtqcgCk1TraWwW9JDQMnKpeU2zX50oI5EoU+3GWNwkVYr9RYHMhv0IzoLNK3zugn9KARNjN5OHooLn+JVSJb1tLCI3pNPwacL+hG5IQGSD6gmW+4ApJ+TMIVAgMBAAECgYAF4go9tmqSHKJhYX8kUlynSxvBL+VfwT8OXui4G5HXTCx+YvQMHfQ5PMADlYjUXa9saZ73pfWiW5DKPT1eaHXnga28e3XwmMkiQhFylgt3tWd4wYyYQ/8iJZt4LFPoh/teBa16mwp37GWbA+i2vHo10EH1ZxhDU1hmA2u3mUKuoQJBAN+T0VtHhko6bXfIo+H8142jDdw0R4iCuOxDjrfvJV7++Lr9PrRGPaNmvSml5NO4MMWM+LhKqiU2jQkQbLNzZnkCQQCXV3v1L1queKUrTYDV9k7cDuOSjkTysgs8rVTSewQ7BWaX+ZvR8nCJDsJyhPpchpxYjYwW/lU9iehnWzJBp0F9AkEAzUEhZJFnYeH9+YgDnEbJhUh6Qvzj5xlLt+vVrFsqjem6Y8B2vn31vHtnkkKwrwZcECD5fgdd6MgJ9pZTlPOO0QJAFzg17YVJbXFXLhCjDrDOopaqNcccLvxAGxwg4nY7TO7kMbb7QDfpKi4YiUd7vgxtGm0FLFXzMBDjlk/4ovgNZQJAIMmmIR7uwJyTKRHHR09Lw21OFCD46uKaAqMrDdgehxSbFItfXE3WwpGeEMwX6fAuEY2U20qMP3GE/rah5P4dpQ==", false);
        System.out.println(decrypt);*/


        /*String publicKey = RSAUtil.getPublicKey();
        System.out.println(publicKey);
        String privateKey = RSAUtil.getPrivateKey();
        System.out.println(privateKey);
        String str = "中国";

        String encryptStr = encrypt(str, publicKey, true);
        System.out.println(encryptStr);

        String decryptStr = decrypt(encryptStr, privateKey, false);
        System.out.println(decryptStr);*/
    }
}

