package com.cmeeting.util;

import org.springframework.stereotype.Component;

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

@Component
public class RSAUtils {
    private static final String PUBLIC_KEY_STR = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANZDOxNiSomQhsqwo56Psi257aHCYTCxpKUdGBp7NRigeuy80ppGEn1CFKx9hK9q/x4WR9RGU9eyCpP5QzyA+EcCAwEAAQ==";

    private static final String PRIVATE_KEY_STR = "MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEA1kM7E2JKiZCGyrCjno+yLbntocJhMLGkpR0YGns1GKB67LzSmkYSfUIUrH2Er2r/HhZH1EZT17IKk/lDPID4RwIDAQABAkAW/xxGFlSdsy9kbdUB3bZoBf6lT/GSgl6Dgj3mCbdHLy/sW8rJ/KYy5+wRpTSYVQBgWbRNMh6yeDaFD18lxZUBAiEA9hkCypO7k3nGzfe3dcSYptXprjSsoZsjVLoGsYJcRMECIQDe4kt+02P73QtdEXX7NUzALQVXygVtpccWCFF6nH3XBwIgEepiNKMqnaLY4TeuaGlmf4bFG0SEaMNlgA6G3DdURkECIQCPLkabeccwRIcJSa9GKq5cgk99Xw1vq+CiOcPGBYQdvwIhAJIXeBm6aeEj7yqWFsS2nVgnTppnMLZmFK8UcGC1EOFn";


    public static void generate() {
        try {
            KeyPairGenerator kp = KeyPairGenerator.getInstance("RSA");
            kp.initialize(512); // 要是需要2048的秘钥的话就修改一下参数
            KeyPair keyPair = kp.generateKeyPair();
            PublicKey publicKey = keyPair.getPublic();
            System.out.println("公钥为：" + new String(Base64.getEncoder().encode(publicKey.getEncoded())));
            PrivateKey privateKey = keyPair.getPrivate();
            System.out.println("私钥为：" + new String(Base64.getEncoder().encode(privateKey.getEncoded())));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }

    // ChatId-87641da-sda==1513538437-问题
    public static String encrypt(String sendMsg) {
        String strKey = null;
        // 公钥字符串,这里直接赋值了，当然一般不会这么写，把公钥放在一个数据文件或者配置里面去获取
        try {
            // 把公钥字符串转换成对象
            byte[] publicKeyBy = Base64.getDecoder().decode(PUBLIC_KEY_STR.getBytes());
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(publicKeyBy));
            // 以上获得的PublicKey可以固化下来，只要秘钥不变，就可以一直使用，但是下面的cipherPublic 不要固化！因为他不是线程安全的，如果使用同一个cipherPublic 并发访问时可能会抛出异常javax.crypto.IllegalBlockSizeException: Data must not be longer than 128 bytes
            Cipher cipherPublic = Cipher.getInstance("RSA");
            // 设置为加密模式并设置公钥
            cipherPublic.init(Cipher.ENCRYPT_MODE, publicKey);
            // 定义一个发送的数据

            // 获得加密的byte[]
            byte[] encryptByte = cipherPublic.doFinal(sendMsg.toString().getBytes("UTF-8"));
            // 转变成字符串以进行传输
            strKey = Base64.getEncoder().encodeToString(encryptByte);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return strKey;
    }

    // Ie2v8fu96HCU2Ls0YpdXy4kxSipp6ptdJUbr/5xzFQpc9sUIWjq5J4x6OzBXwoumhCC3/vYM/Wwo5Ik8PcjA0A==
    public static String decrypt(String encryptReceiveMsg) {
        String receiveMsg = null;
        // 私钥字符串,这里直接赋值了，同样的，可以把私钥放在一个数据文件或者配置里面去获取

        // 刚才我们获得的加密数据，一般通过各种传输途径接收到
        try {
            // 把私钥字符串转换成对象
            byte[] privateKeyBy = Base64.getDecoder().decode(PRIVATE_KEY_STR.getBytes());
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKeyBy));
            // 同样的，可以固化cipherPrivate ，但是不能固化cipherPrivate，因为它不是线程安全的
            Cipher cipherPrivate = Cipher.getInstance("RSA");
            // 设置为解密模式并设置私钥
            cipherPrivate.init(Cipher.DECRYPT_MODE, privateKey);

            // 进行解密
            byte[] decryptByte = cipherPrivate.doFinal(Base64.getDecoder().decode(encryptReceiveMsg.replace(" +", "+")));
            // 转换成字符串
            receiveMsg = new String(decryptByte, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return receiveMsg;
    }

    public static void main(String[] args) {
        System.out.println(decrypt(encrypt("c06fe7cf-2a89-4099-9805-ce03031938f8")));

    }
}



