package com.lsw.utils;

import org.apache.commons.codec.binary.Base64;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import java.io.UnsupportedEncodingException;
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.HashMap;
import java.util.Map;

/**
 * Created by crazyDream on 2020/6/30.
 */
public class RSAUtils {

    public static final String KEY_ALGORITHM = "RSA";
    //public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
    private static final String PUBLIC_KEY = "RSAPublicKey";
    private static final String PRIVATE_KEY = "RSAPrivateKey";

    /**
     * 默认的公钥
     */
    private static String public_key = "";
    /**
     * 默认的私钥
     */
    private static String private_key = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDQR5O/78A2rNMuPXy66uU0v4Ps\n" +
            "PaUxIx0Uox8iYgFO44uyfiQ9JpD/j52G2cu/2At+hvm2ZILhfusFLHeEb83hzmhBHIVwuxiAuKGB\n" +
            "SYakQYw7k+NdJjfckxyZlvMHlweFgQrWYn8jj78GReWa4K/Swq7KJX+yeRB65lEVWJC0vhWbOcoW\n" +
            "iW2cocBsuhkUBqOlPimNQsNoO1N0nxpIt1VALIfQRKN/guAhSrZVXXjPQmFqUAasup7k7h1gtGI1\n" +
            "pBgBqaINRp3L6Jqe23FgN+6p8Ap732ZGsaGRtXKWzQhlwHc8jGFhJcKSkHtp8bQBmSnvYCWIsRjw\n" +
            "zt5UkwObhi+/AgMBAAECggEBAITiNfUObO81QqNM3YiQF16ZFf0is4NvKL2i+VlBeB4x9U4TRuGw\n" +
            "+m/i3BlOWb1zhJncWfOxmwNtq1qorTRU9OEthLyOCuEKra5qnbhUBdBEdckJKNWkbZ2QSn3/ndzo\n" +
            "0gaudxCi1QUGUFUbQUuYMPVh+ozEcf2XWhlfWroowGJfgbse7+aOylsdI2KTbsqvEygwUD58JgaC\n" +
            "kLX39YQ7WT+/eSv20Te9YsObLIVfz7f8YGEQx1mpBY94Qqcb28HCKA6+UashetsCch0bKy+4cshd\n" +
            "DR9T+6J5KcE73PyZZWAM0qpMlWkXWZpe08834N9XWgKnmNY7i++h/CcKMlcg6XkCgYEA7YvTKRxE\n" +
            "dubwePmzCOEEWguaMLWZO7LCIT0rwZYGjuGElRk29R/t0JflIjVsojM2iSWzCPupgGJErYMU5UqP\n" +
            "fegW2AUYIYSDb8DIkIOK1pWO1SzfXWHPvWJnKrA778MDY0uU1t8yY3x9qCaTxSxMoMVk2sK15FB/\n" +
            "y0qs3fYLYN0CgYEA4HW3SueOB7ZmUXxgtOZcuVDVw3+TUIdl4/x2WxQYG4I0eN/qQVi9X88PF2f4\n" +
            "TRMzpRl/Zf3qCCRT1/0gUYGJB0uV9UdNuokbKgA2CC5unfSOVY2wEBqERubJgcxcMrC4nchOUSXe\n" +
            "qTBDUHfLuJSVMgjhMerE3gv/e7PeoeaHm0sCgYEAuAwC4jJFlX5eyMxme7Wj4oRkxeKdw9Q/dvNn\n" +
            "KIktsZxnVgIAQ7GmV1yoqnWMIqvdUCuGaKpb7N22al1KXlEDlkCxGlPwG2AJWhebDeTtOE8OKHqo\n" +
            "4Tg8dXZ9imSbO6vzvwY7XrP13YEB9rtU+IrXICVwe9IqjagVK5RDFYJh1H0CgYEAyOnVhWC7C0BD\n" +
            "WdEBJyvD98TZcsKw9DYeB/KlZmUYJxdnLIMRRijOagIHOiZAZY04fyHRnVOotlz+B6l10j8mjrcj\n" +
            "pYeLldq/y9qggrY9IXoUJZRL8j4qBOTznhF0vZLdza3MHGrPYZXnyxFP8wpceYrlOC8yxKbsqqeY\n" +
            "MkcNPv0CgYAJSSe4uGdGtv+7vEKa+WoR7JDefDd178l1o7t/otkrAzSRFPP+tKoeZsWZEbkWZs7i\n" +
            "3JP80JOSE+L/RTS14EII/qQvmQgfjE4X9p+2zpKdGPFTyHN4KENPrJfr0iqiQZq/PxfYHQmzi5uH\n" +
            "TIBmGqtRD7NEjJFIdN9R+Ejq0qiy5w==";

    /**
     * URL 解码
     *
     * @return String
     * @author lifq
     * @date 2015-3-17 下午04:09:51
     */
    public static String getURLDecoderString(String str) {
        String result = "";
        if (null == str) {
            return "";
        }
        try {
            result = java.net.URLDecoder.decode(str, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return result;
    }

    //获得公钥
    public static String getPublicKey(Map<String, Object> keyMap) {
        //获得map中的公钥对象 转为key对象
        Key key = (Key) keyMap.get(PUBLIC_KEY);
        //byte[] publicKey = key.getEncoded();
        //编码返回字符串
        try {
            return encryptBASE64(key.getEncoded());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    //获得私钥
    public static String getPrivateKey(Map<String, Object> keyMap)  {
        //获得map中的私钥对象 转为key对象
        Key key = (Key) keyMap.get(PRIVATE_KEY);
        //byte[] privateKey = key.getEncoded();
        //编码返回字符串
        try {
            return encryptBASE64(key.getEncoded());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    //解码返回byte
    public static byte[] decryptBASE64(String key) throws Exception {
        return (new BASE64Decoder()).decodeBuffer(key);
    }

    //编码返回字符串
    public static String encryptBASE64(byte[] key) throws Exception {
        return (new BASE64Encoder()).encodeBuffer(key);
    }

    //map对象中存放公私钥
    public static Map<String, Object> initKey()  {
        //获得对象 KeyPairGenerator 参数 RSA 1024个字节
        KeyPairGenerator keyPairGen = null;
        try {
            keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        keyPairGen.initialize(2048);
        //通过对象 KeyPairGenerator 获取对象KeyPair
        KeyPair keyPair = keyPairGen.generateKeyPair();

        //通过对象 KeyPair 获取RSA公私钥对象RSAPublicKey RSAPrivateKey
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        //公私钥对象存入map中
        Map<String, Object> keyMap = new HashMap<String, Object>(2);
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
    }

    /**
     * RSA加密(默认公钥)
     * @param str
     * @return
     * @throws Exception
     */
    public static String encrypt( String str ) throws Exception{
        return encrypt(str, public_key);
    }

    /**
     * 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);
        byte[] bytes = cipher.doFinal(str.getBytes("UTF-8"));
        return Base64.encodeBase64String(bytes);
    }


    /**
     * RSA解密(默认私钥)
     * @param str
     * @return
     * @throws Exception
     */
    public static String decrypt(String str) throws Exception{
        return decrypt(str,private_key);
    }

    /**
     * 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);
        return new String(cipher.doFinal(inputByte));
    }

    public static void getKeyPair() {
        Map<String, Object> keyMap;
        try {
            keyMap = initKey();
            String publicKey = getPublicKey(keyMap);
            String privateKey = getPrivateKey(keyMap);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

// 使用范例
    public static void main(String[] args) {
        try {
            //私钥
            String privateKey = "xxxx";
            //tocken获取的加密串
            String token = "f9DYDUfoDAlPktNKFKcYyhiTGIMKVX3gzg//S41tNvJqk59qWJFXa0sygcGFy0V6PQhEmx3WMTsnZZk3sSuF0gqsOvOXKK9MNd8++8+s9U0jIIGSs1lLbSz9Bu1fUurpNDa+IpORZjcci3prBdTbIkmp/AxsgUSerUiGn8pB7Gu3C/CslNxROojMF0/1HhJHzZiGEc7zYbbP9BCzMY7jXJAnXW0k93VYNPoRewyL9eTT0WiwTFkbzg86Dfbh6Kp3DUafP+jWU2VzXWHMwVU29ZIA6jXES40cR9ihXfchPVQkxJx2VHVGrjrGnumjKJ2FDWD0ND7ZmWOxT7I6n2KKgg==";
            String s = RSAUtils.decrypt(token,privateKey);
            System.out.println(s);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}

