package com.template.common.utils;

import net.sf.jsqlparser.expression.StringValue;
import org.apache.tomcat.util.codec.binary.Base64;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;

/**
 * @Author: codingliang
 * @Description: TODO
 * @Date: 2022-08-04 10:53
 * @Version: V1.0
 **/
public class RSAUtils {

    /**
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;
    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 128;
    private static final String ALGORITHM_NAME = "RSA";
    private static final String MD5_RSA = "MD5withRSA";

    /**
     * 获取密钥对
     */
    public static KeyPair getKeyPair() throws Exception {
        KeyPairGenerator generator = KeyPairGenerator.getInstance(ALGORITHM_NAME);
        generator.initialize(1024);
        return generator.generateKeyPair();
    }

    /**
     * 获取base64加密后密钥对
     */
    public static HashMap<String, String> getKeyPairMap() throws Exception {
        KeyPairGenerator generator = KeyPairGenerator.getInstance(ALGORITHM_NAME);
        generator.initialize(1024);
        KeyPair keyPair = generator.generateKeyPair();
        String privateKey = new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));
        String publicKey = new String(Base64.encodeBase64(keyPair.getPublic().getEncoded()));
        HashMap<String, String> keyMap = new HashMap<>();
        keyMap.put("privateKey", privateKey);
        keyMap.put("publicKey", publicKey);
        return keyMap;
    }


    /**
     * 获取公钥
     *
     * @param publicKey base64加密的公钥字符串
     */
    public static PublicKey getPublicKey(String publicKey) throws Exception {
        byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_NAME);
        return keyFactory.generatePublic(keySpec);
    }


    /**
     * RSA加密
     *
     * @param data      待加密数据
     * @param publicKey 公钥
     */
    public static String encrypt(String data, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance(ALGORITHM_NAME);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        int inputLen = data.getBytes().length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offset = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段加密
        while (inputLen - offset > 0) {
            if (inputLen - offset > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(data.getBytes(), offset, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);
            }
            out.write(cache, 0, cache.length);
            i++;
            offset = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        // 获取加密内容使用base64进行编码,并以UTF-8为标准转化成字符串
        // 加密后的字符串
//        return new String(Base64.encodeBase64(encryptedData));
        return new String(Base64.encodeBase64(encryptedData));

    }


    /**
     * 获取私钥
     *
     * @param privateKey base64加密的私钥字符串
     */
    public static PrivateKey getPrivateKey(String privateKey) throws Exception {
        byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_NAME);
        return keyFactory.generatePrivate(keySpec);
    }


    /**
     * RSA解密
     *
     * @param data       待解密数据
     * @param privateKey 私钥
     */
    public static String decrypt(String data, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance(ALGORITHM_NAME);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] dataBytes = Base64.decodeBase64(data);
        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, StandardCharsets.UTF_8);
    }


    public static void main(String[] args) {


        try {
            // 生成密钥对
//            KeyPair keyPair = getKeyPair();
//            String privateKey = new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));
//            String publicKey = new String(Base64.encodeBase64(keyPair.getPublic().getEncoded()));
//            System.out.println("私钥 => " + privateKey + "\n");
//            System.out.println("公钥 =>" + publicKey + "\n");

            String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMw5w8HTq7nIrJCw+N9VaJaBsQit3XiSJc02KFyJpUpvoeeRC+rvOlC5nzRYRf3iymdQwjeI4CX8aYi8eukbBxsHiElvOeb49qOLCdRI+4IJcDrxgkXrjRwkpv/wp4ztZXPr04WQgQ8eFXE7LgUUXlBZ7+S3rM5nX0eYT5qT7nH9AgMBAAECgYEAktdN68XYicLCYV798wckJmOl+QmaXqEm0QCJ0M+fq3/MuAXQveG42mY9FJQL71rsEZE9tFSUZnuxHgH3ljg6yGfMvrgQ5Nwsoj5eG52mYXw9JYJHA5JOC7eoZ0HxcMuDOJtuGWDQcm9/UHUKkLnTFwX8R9VqDL7Wn+R5RrTjmAECQQD+uX2K9u4g49j342IQzrnGYlSjpwXPhy+P/q/UTJHhTE3L0AKeZ/C5ZfEzc57vwwbDzTXRaFtr9DcYV8rODoUBAkEAzT+LRUfuuPfuAyjpp0NPm+iAkwtoIWdSU3bezeoH2jcMxcMCkN1PBvY79Nluj8Ml5gsjipXtkl0sqv0bhpUA/QJBANcRemRolSqD9l9mRxh10vkjcN80WH2eYJQtr/uKIumc6VqaaHuiuuduoTaV+q3pdr6/dx82A2qkqhgNmBhevgECQBCR/8FxJEHEqm+Q3wRE9+ljZPX6JscDm27nmudO7KFebmaM7ukZJOcv+/kxkK6El8uxvIXUwuBdK10GoDFGWFUCQEhiWAd+RB+tI0ndG4+i+CWIBaxArbOr5eaC0PJCu7GxRZtcxzyittv5u6jMiKYhnJatOLVGpo043NXj/QxI2lY=";
//            String privateKey = "-----BEGIN PRIVATE KEY-----MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMw5w8HTq7nIrJCw+N9VaJaBsQit3XiSJc02KFyJpUpvoeeRC+rvOlC5nzRYRf3iymdQwjeI4CX8aYi8eukbBxsHiElvOeb49qOLCdRI+4IJcDrxgkXrjRwkpv/wp4ztZXPr04WQgQ8eFXE7LgUUXlBZ7+S3rM5nX0eYT5qT7nH9AgMBAAECgYEAktdN68XYicLCYV798wckJmOl+QmaXqEm0QCJ0M+fq3/MuAXQveG42mY9FJQL71rsEZE9tFSUZnuxHgH3ljg6yGfMvrgQ5Nwsoj5eG52mYXw9JYJHA5JOC7eoZ0HxcMuDOJtuGWDQcm9/UHUKkLnTFwX8R9VqDL7Wn+R5RrTjmAECQQD+uX2K9u4g49j342IQzrnGYlSjpwXPhy+P/q/UTJHhTE3L0AKeZ/C5ZfEzc57vwwbDzTXRaFtr9DcYV8rODoUBAkEAzT+LRUfuuPfuAyjpp0NPm+iAkwtoIWdSU3bezeoH2jcMxcMCkN1PBvY79Nluj8Ml5gsjipXtkl0sqv0bhpUA/QJBANcRemRolSqD9l9mRxh10vkjcN80WH2eYJQtr/uKIumc6VqaaHuiuuduoTaV+q3pdr6/dx82A2qkqhgNmBhevgECQBCR/8FxJEHEqm+Q3wRE9+ljZPX6JscDm27nmudO7KFebmaM7ukZJOcv+/kxkK6El8uxvIXUwuBdK10GoDFGWFUCQEhiWAd+RB+tI0ndG4+i+CWIBaxArbOr5eaC0PJCu7GxRZtcxzyittv5u6jMiKYhnJatOLVGpo043NXj/QxI2lY=-----END PRIVATE KEY-----";
           String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMOcPB06u5yKyQsPjfVWiWgbEIrd14kiXNNihciaVKb6HnkQvq7zpQuZ80WEX94spnUMI3iOAl/GmIvHrpGwcbB4hJbznm+PajiwnUSPuCCXA68YJF640cJKb/8KeM7WVz69OFkIEPHhVxOy4FFF5QWe/kt6zOZ19HmE+ak+5x/QIDAQAB";
//            String publicKey = "-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMOcPB06u5yKyQsPjfVWiWgbEIrd14kiXNNihciaVKb6HnkQvq7zpQuZ80WEX94spnUMI3iOAl/GmIvHrpGwcbB4hJbznm+PajiwnUSPuCCXA68YJF640cJKb/8KeM7WVz69OFkIEPHhVxOy4FFF5QWe/kt6zOZ19HmE+ak+5x/QIDAQAB-----END PUBLIC KEY-----";
            //            System.out.println("私钥 => " + privateKey + "\n");
//            System.out.println("公钥 =>" + publicKey + "\n");

            // RSA加密
//            String data = "admin.123456";
//            String data = "15079248859";
            String data = "143891";
//            String data = "{\"telPhone\":\"15079248859\",\"token\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwaG9uZSI6IjE1MDc5MjQ4ODU5Iiwicm9sZUlkIjoxLCJleHAiOjE2ODI1ODM1NzUsImlhdCI6MTY4MjMyNDM3NX0.AhwOa7220k00hIlkhkHMHnRX-tRXTgntyU7Cdv2YvSs\",\"tokenTtl\":1682583575276,\"userName\":\"朱秀平\"}";
            String encryptData = encrypt(data, getPublicKey(publicKey));
            System.out.println("encryptData = " + encryptData);
            System.out.println("加密后内容 => " + encryptData + "\n");
            // RSA解密
//            String s2="mbGB7v0FmeFiQSOd5h+PdMPxe/QeFFvTQ8wXgS+jfAw3Y/Yh5YQPuOaPh8bSKu2NtNU0LIWqVRLEhN3V7kwtTKTnqL/6crAdKlLsU9fkM6yLQWVPQjkPhfDPzm1yY9dS3ON3rv4Ofa/boyI3+91zs8JYHKJ0xv+fDSZtNwDKX5oFlhf7GkD///5U6T6wmY/Cmqd6R76bkOEqC0E9jd1U6DEDJ7kq9oMxE/pkAxx952kDQEE2b3smK21odAU0Sr3w8j/LkOPRvSwkt7W587RFvtwE8MAKAR2+LJPQ3x7yQT7EyOwtlPUwfm+QFOXWVy+sKWiMMcdKRseMsfGrWBC17oREwpimdb1ZdYeOYxGd49hiS1ygbsa585yOhJ9TSeLG/K6tuhj1NqH+UuzJHVIC6xI0BgqSMOIs/zB8v07xRGNyZg9gZg3/86sgY6f8Xyj2nnplBxxEBx5MSMvtvqh2NkxDZQOExdwbO4FbzmkzDR4fp2wEFzjN3DCm8x8HJdhtoFXRO/nJlVDKmLkCMGCq/drAjvBsPbcIAL8lMaaC5/a/S3/SM83X/4KXb6LsGQrVyubYjACX3l+QQ/2H85/kOo3Tn38Yn6Vxjm/bIH/8FzGDK33MpxEEeeDCeh6dhfyhhvDDdvvafWUZbUIL7nelFfY5cnu9vbwi/nHZSFQBI/o=";
            String s1="rJkG8pebNdrRNzeFE4l+fDaIFwNOR8aNR6kIuQT3vtnWLXxGog8UKxvvtptnMyDd9WnMmB2ADO5XVqan/fyo+eB4pXk48WJu86QP0hq0wLwYKLAz85GZmqy6oT7rAk39ZXZSUN2kwyTSaEbRpYoL4Qp+Dly3+3I2vbXPxJI/0jUPn/pHm5JjvR2w3XD64ikmhoR30gArx8Biw2hqoTGDbZNFd/2Ya0GW/AxHa1s+chm3Mw7Xctt845aXgyq7Xq8ITWLIDSpXkTV3rUK53SS/H0eWrDJvqy96GCRo4+Rh4nf+XCbp4corUaHawG9rcpjeNdHqCwZVRrvnHRzN09l6IFp9v6jNR5HcLbo77DEe6Gh0e7hLEKuryk0jbFDfRkP4AsFYonQoZ/Kstjt9bETh5m95mWEZ1PRvRYT9FUDnvOanRjrPYIfnV+C2+/JsLc13UrbpgqVz0X62pLiRZzLy7sDRYSTUuGvYF+3DhgPe/xHfYVloFEO5tBlWgP2LjCpn";
            String s3="kSPQjALkcaXKlKRFZlA4U4tMnBs4QE6Qn9hb/vyGaBCm0DAQ3/QYddwfUwabAX+z2scvmOru4k1hiAUymbfH6pGy+6G63meYN4AH97N+4U0I7+B8O1IjWszRaQd3rAH8mOyq4Nwev2kNDsviBTf8bYXdpZTQT6DpTGfqIy/Z5Kib0ofwTvZ/PRHGhEmehEb1SoRytpzSvtWTFhZg7Z8APyxPyI74YDfKEbU5ywZWiSDn2uK8VlYFAzzWtrVQdVrD5Tt0hZ3Hvrc5YfS1h/sic2bImWI6vf3SqJe23JQWgv6KHETF1cRC4B+g3NcvvCNt9q0v2kp/OAKD4OWVIKKd8DS4Q/YWS5G/y+6oExXTfvw7xD8AMSszqoED4/3Mu5ytL4SR4Dpazs3KMEPE2jUEMNtQ9miqIIBcw+9VS9/m1+MvtvUtVewKgleXURECXV6QfvMlt+wTkj7c+Ww8JdR0RONUqFOwNyQkKCM7QjBZYSnkkUoAZF/+/sa2bF7Myp9l";
            String S4="UypmNTjrrus/yh5vfbu7U4M4TY+GafpxDpHt9nhZpdRwxn5IZVwJs/uvyjb0j2jrHM352snw0MyGHv+bHpBWovryuj5ovY8yejg8Stx1OTjPY7X4Kf2P+ooZQBpQUo44uhq8y4IgSGoOFqUvvMr9z5S78OYbu8wrRfbV5u7LGEI=";
                          String decryptData = decrypt(encryptData, getPrivateKey(privateKey));
//            String decryptData = decrypt(S4, getPrivateKey(privateKey));
            System.out.println("解密后内容 => " + decryptData + "\n");

            String substring = s3.substring(0,100);
            System.out.println("substring = " + substring);
            System.out.println(substring);
            System.out.println("substring.length() = " + substring.length());
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("RSA加解密异常");
        }
    }
}
