package com.lantone.qc.security.util;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.ArrayUtils;

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.LinkedHashMap;
import java.util.Map;


/**
 * @description:
 * @author: zhoutg
 * @time: 2019/10/29 10:00
 */
public class RSAEncrypt {

    // 公钥
    private static final String pubKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkoEsfWLLa3Y8hlxG7QB9Rew7iMJ3b7Dev3euMckA0F1Ewq3v4nBHQyX75ZOn2blMU1qm46OPJAE05Pgt2MMYOhdvMR5jDNQSrynMx/0lMkY24u+nfM+kMuAIxQOHwSQN7N2dJY1v1vn4fAChL5PiJIpy6Ub5r9HIF6nUWTso2FwIDAQAB";
    // 密钥
    private static final String privateKey = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKSgSx9YstrdjyGXEbtAH1F7DuIwndvsN6/d64xyQDQXUTCre/icEdDJfvlk6fZuUxTWqbjo48kATTk+C3Ywxg6F28xHmMM1BKvKczH/SUyRjbi76d8z6Qy4AjFA4fBJA3s3Z0ljW/W+fh8AKEvk+IkinLpRvmv0cgXqdRZOyjYXAgMBAAECgYBwJhrHIf/GBgWJ1oZnz8kGExUSlhgUSBmvnzjmFrcSRYgz5b6woHGqkHoFn++ax5Glso8wvsbemWwCQPhB7fwdsD6dn4YD+KidxAQCR3V4kqt8yxsG2ZyiPjeGtFqAUZHRQF0FxXl40FEjGbCymy2HnR+tDXYn9KinWNN1z1zjMQJBAPaKanseVGKZ43oufGad9rBeb/WCQNOwsInDRSAGC5xEmJ8AD0RApTI3G2AUj8K6jSg/OYh332qNFk/KKcpUrzsCQQCq8UrfmPO+WzHuHXnFWZpXvY8scq9+cPeIXNNbsb6Zw+0lFFvJ52LLdHE1bQjSKQz4RUsKaxbfU8wIj5Gvqp7VAkEA6mHjI1NNREQq+ABzshcg7MGLTOtc+CP1YbMr52r35MNuGVM0MF4I7zlmpCxIFAfIpOeeqbfUxfaFrKt0mW9y+wJBAIIKjasL8GEffxxlz/0R7RhSXFiz5k2KIsTZ2PAoh5byNbW/hxRRshaUvoqmJ8+46uTz0eJbFUtPtCfPEEVSxwECQQDZNVxuvdUNeImElaSIbF8NS7hnvMF8mNzgOQwOoXJ2gB9+BNQebiZiJC17oL29hPOCfvDS+4Hmt5UtOfjU9Zf1";

    public static void main(String[] args) throws Exception {
        System.out.println(RSAEncrypt.decrypt("asExoAAig485baqFxGRR+EXrnLoJ2UFb1qc1/X1m0EA/4q2nUquMfvDGYjMM8cXjDQ+0YabTxe9mM9iApTlc7aFNL/JLUDgdFO5VuzjUeJtTPAKbR179SAmJmCQIbeRlo6MywsZJEojhWpUfO27oRJ12RPwWpoTKsOFuL0QSGjMYVWZfJQP4Pshn0pv7CrCcodYjm4ZCyFIcJefsXYdepb/6Dc3DIh4lZLfXu7R0B3L0SRGweTQUvfGnq5Eo27dnV7oVGYORc5/fD4/1SoIUqK3hUOsbUc5Ap3HuGStFqipOEj0T1AORSsVUWXER/qef0BtASfYjI3/tMCCCWURRzIV2pwvOJ0h8w3ToaBYfcwGRa9SEWL3Vx6M6B2E0K2oRlu8JdXQVsarB7lNQyohDJPbgOSaanop+GofZE3bNQlr/KB+cXOdrHMPrp0tn6AkzrvhuokiIQ3UFNqduasXOXpKsRZRQn7H9Bng+2QjQ6p2G3h/SZZy3uO9TpWH4jiYDiCTzYep5l74isKXymV4zleEOX2kWzm71e6J6WC3hZJ63lH5R9LJxihwFgTknhsmcAVM51pH97QAKBa8kK0gtloRhOzVs7Z061orw7bRpgV0wCIMK4WsXf8EY5hbQ0+0r4r73gbMJm8n6PItxDo2dJEe6ztmA6OfZc5pFTcgHGM0="));
        StringBuffer sb = new StringBuffer();
        sb.append("server.cpu=E3060500FFFB8B0F") // cpu信息
            .append("$$")
            .append("server.key=" + RSAEncrypt.encrypt("c75bc6d5-fcac-4fc2-9265-0d57ce1c4958"))  // 加密key信息
            .append("$$")
            .append("server.remainday=365") // 剩余天数
            .append("$$")
            .append("server.validtime=30")// 有效时间
            .append("$$")
            .append("server.hospital=嘉兴人民医院") // 医院
            .append("$$")
            .append("server.provider=华卓"); // 服务商
        System.out.println("加密文件：");
        String en = RSAEncrypt.encrypt(sb.toString());
        System.out.println(en);
        System.out.println("解密文件：");
        System.out.println(RSAEncrypt.decrypt(en));

//        System.out.println(RSAEncrypt.decrypt("Vhjgh3BhOGUHr7lnba+j2uYhQYdccbIBGxb4VZ/yQMgTzjTsnwU7OtY/jHqp38qg3hN1ACYpUJKSCvpd3eDD6fuB6mm19oGf4zrmbtnnOTKoGkiIlL5jHuDPXkuiCimBIJQn39lthzB519GbKwclBzhapoq72J4FK0/xvfJDSwWEhc68Ib3t07810Yv1ziRI3bgycxsEVei1wlnSEfvt5NcFkvEVvlom8xzD+bvQW8UuVI9Iz2tS0J0UqmkKB0GPjDZ+86agONYcsD3c607JEKk3/pnd++OJRNiFjw3dkSVDFNfZNG/kiSEOPYV0v0TgbpRMixjA4AL1eLu0FDSjYg=="));

//        String ss = "server.mainboard=mainboard--info$$server.disk=disk--info$$server.cpu=cpu--info";
//        System.out.println(decrypt("fDGfXzuP/YVAcvX0BLKVI3ID7dxiwLIYMPzRdxQOSy7e7zAj490nM0JmoTpT/wRmZD/ABhaaZqcV5/Wc+oDlB/9obTn5D4pJD+ZPIv1entbpKxV2iCEsM/0dkrbEypjBh9fdhJv0cewmkYiJwZwzOPMefvu/zU0fC3f49NmT2Lo="));
////        System.out.println(encrypt(ss));
//        System.out.println(decrypt("TuiVlz2EMz29pDpv2xVENi/1wTh/cAPvrfSnsW5HIhYcW/hYmjWP76L+qGTKY3xI7ICl1XD1Mik1xSECGw0INKdkTC3DFyGUuMQ/bIM42SVIntx6nmou9LxX4j0BkO/1nplZiHDLtOEAxVxXFz7ckt6eP4N7BNQ0+Onu/HDMZVs="));
//        System.out.println(encrypt("server.key=123"));
////        System.out.println(encrypt("server.disk=456"));
////        System.out.println(encrypt("server.mainboard=789"));
//        //生成公钥和私钥
//        // genKeyPair();
//        //加密字符串
////        String message = "300";
//        String message = "2019-11-21 00:00:00";
//        String messageEn = encrypt(message, pubKey);
//        System.out.println(message + "\t加密后的字符串为:" + messageEn);
//        String messageDe = decrypt(messageEn, privateKey);
//        System.out.println("还原后的字符串为:" + messageDe);
    }


    /**
     * 随机生成密钥对
     *
     * @throws NoSuchAlgorithmException
     */
    public static void genKeyPair() throws NoSuchAlgorithmException {
        // KeyPairGenerator类用于生成公钥和私钥对，基于RSA算法生成对象
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        // 初始化密钥对生成器，密钥大小为96-1024位
        keyPairGen.initialize(1024, new SecureRandom());
        // 生成一个密钥对，保存在keyPair中
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();   // 得到私钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  // 得到公钥
        // 得到公钥字符串
        String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
        // 得到私钥字符串
        String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
        System.out.println("公钥:" + publicKeyString);
        System.out.println("私钥:" + privateKeyString);
    }


    /**
     * RSA公钥加密
     *
     * @param str 需要加密的字符串
     * @param publicKey 公钥
     * @return 密文
     * @throws Exception 加密过程中的异常信息
     */
    public static String encrypt( String str, String publicKey ) throws Exception{
        //base64编码的公钥
        byte[] decoded = Base64.decodeBase64(publicKey);
        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
        //RSA加密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);

        // 加密时超过117字节就报错。为此采用分段加密的办法来加密
        byte[] data = str.getBytes("UTF-8");
        byte[] dataReturn = null;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < data.length; i += 100) {
            byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(data, i,
                    i + 100));
            sb.append(new String(doFinal));
            dataReturn = ArrayUtils.addAll(dataReturn, doFinal);
        }

        String outStr = Base64.encodeBase64String(dataReturn);
        return outStr;
    }


    /**
     * RSA私钥解密
     *
     * @param str 加密字符串
     * @param privateKey 私钥
     * @return 明文
     * @throws Exception 解密过程中的异常信息
     */
    public static String decrypt(String str, String privateKey) throws Exception{
        //64位解码加密后的字符串
        byte[] inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));
        //base64编码的私钥
        byte[] decoded = Base64.decodeBase64(privateKey);
        RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
        //RSA解密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, priKey);

        // 解密时超过128字节就报错。为此采用分段解密的办法来解密
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < inputByte.length; i += 128) {
            byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(inputByte, i,
                    i + 128));
            sb.append(new String(doFinal));
        }
        return sb.toString();
    }


    /**
     * RSA私钥解密
     *
     * @param str 加密字符串
     * @return 明文
     * @throws Exception 解密过程中的异常信息
     */
    public static String decrypt(String str) throws Exception{
        return decrypt(str, privateKey);
    }


    /**
     * RSA公钥加密
     *
     * @param str 需要加密的字符串
     * @return 密文
     * @throws Exception 加密过程中的异常信息
     */
    public static String encrypt(String str) throws Exception{
        return encrypt(str, pubKey);
    }


    /**
     * 将密文解密，转成Map
     * @param str
     * @return
     * @throws Exception
     */
    public static Map<String, String> convertMap(String str) throws Exception{
        Map<String, String> map = new LinkedHashMap<>();
        String strDe = decrypt(str, privateKey);
        String[] item = strDe.split("\\$\\$");
        for (String s : item) {
            String[] keyVal = s.split("=");
            map.put(keyVal[0], keyVal[1]);
        }
        return map;
    }
}
