package org.springblade.common.utils;

import cn.hutool.core.codec.Base64;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;


/**
 * @author: lianghanqiang
 * @description: 秘钥工具
 * @since: 8/2/21 -- 9:40 AM
 */
@Slf4j
public class RSASecretUtil {

	public static final String CHARSET = "UTF-8";
	public static final String RSA_ALGORITHM = "RSA";

	/**
	 * 	生成秘钥对
	 * */
	private static void generateKeyPair() throws NoSuchAlgorithmException {
		KeyPairGenerator keyTools = KeyPairGenerator.getInstance("RSA");
		KeyPair keyPair = keyTools.generateKeyPair();
		System.out.println(Base64.encode(keyPair.getPrivate().getEncoded()));
		System.out.println(Base64.encode(keyPair.getPublic().getEncoded()));
	}

	/**
	 * 得到公钥
	 * @param publicKey 密钥字符串（经过base64编码）
	 * @throws Exception
	 */
	public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
		//通过X509编码的Key指令获得公钥对象
		KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
		X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decode(publicKey));
		RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
		return key;
	}

	/**
	 * 得到私钥
	 * @param privateKey 密钥字符串（经过base64编码）
	 * @throws Exception
	 */
	public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
		//通过PKCS#8编码的Key指令获得私钥对象
		KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decode(privateKey));
		RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
		return key;
	}

	/**
	 * 公钥加密
	 * @param data
	 * @param publicKey
	 * @return
	 */
	public static String publicEncrypt(String data, RSAPublicKey publicKey){
		return encode(data, publicKey);
	}



	/**
	 * 私钥解密
	 * @param data
	 * @param privateKey
	 * @return
	 */

	public static String privateDecrypt(String data, RSAPrivateKey privateKey){
		return decode(data,privateKey);
	}

	/**
	 * 私钥加密
	 * @param data
	 * @param privateKey
	 * @return
	 */

	public static String privateEncrypt(String data, RSAPrivateKey privateKey){
		return encode(data, privateKey);
	}

	/**
	 * 公钥解密
	 * @param data
	 * @param publicKey
	 * @return
	 */

	public static String publicDecrypt(String data, RSAPublicKey publicKey){
		return decode(data, publicKey);
	}



	private static String decode(String data, Key key ) {
		try{
			Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
			cipher.init(Cipher.DECRYPT_MODE, key);
			return new String(cipher.doFinal(Base64.decode(data)),CHARSET);
		}catch(Exception e){
			throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
		}
	}


	private static String encode(String data, Key key) {
		try{
			Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
			cipher.init(Cipher.ENCRYPT_MODE, key);
			return Base64.encode(cipher.doFinal(data.getBytes()));
		}catch(Exception e){
			throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);
		}
	}


	public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException {
		String PRIVATEKEY = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCVj9vx7e6z+5kD43EnxZvfIZ299SwYxYzjAgIfweu/Ot73mRzAzVbbCsbUuWGYgqpN9otzjHze3hGOys61SA8hCUhg4yuzkZu/C7F5pgN9AkUOhcS2qgOyuwlWnxn8QyyyZGnIBH1Juua0UUi6oRKK7geOmGViXuoYUGoX1rLv2TQLVSOe1vf377BmPmtjForS8OgGWJ1bO5zo8V6yGGV2g8dj2A1Q+xbUKPVsU+0xCVSrJbLWgJx7apKkX+E9xoh8J01T3hE6/m1SSQePcDZsjOoy93CeCLNY0tmw5F93gpwlO4L+oxGVQHWtku6dHW8TVP7t9DAW+UcDwsaVaNk5AgMBAAECggEAH52/ow7nLQj8ucO0wfGWF78ld2iCn+Hy/HIKPOhji5NIWxL07xT5TWijy4g8x16n3b9Gj3CdXQeYspTQyaWn/RXXRRQAwv7+643vQIYFqsF2E7HXeb3K9ldvi+4qMheJNVTgv7WjPpjR+EBOnZU7ND9JPa2dkQP7fJRTOSLbxLPTa3pIBQqsuNZyPI3h3XxIyXya24ncenVLRJNsYUgA63KOS79sft3kqPuEVDOWrenvAEeby4bCbx31Z3pPlXiA/5O4vDQrb3GxCj6qKs3CJ9mqVItQg0W1GJALC9NMwOUVgv5CNKGfhwByfgit2/ODGceRkuirnj9u9VXq1cUVYQKBgQDt2EOWUFDQg8pFj6yzi6nkhq6k/DYTOXi9jX7HEg6YPTb0ah5DOvL0/q9zFvDNZyNbmJ0KQye3Ep9teTkTQ3S63T6AsXuMWa7hy5gUAstRZIcKbwIxdBQHb7gNSX9sugrr5uuYCXNMo29uPcVvxsoPSe+VWvqSDafGfgezCGcvXQKBgQCg+nTKVcE3K1tH0lElk/m1dFTOzsTai0b2FowcnqnukaxvqreavS4rY7feNqQBDL3uiSdsdnlFY3bpMrIvqKSwT/5D+CUafRAePvak87fV9c548pqlYCrX69GFMMQHBputSRIkCiTwIrX8ainjt7yuhJH1E81VU0lZaGhmmT2fjQKBgB3jy7qcJUvPBCBxydZWeudJNbFuMK2Bz3aizYfe8Q6Ywss8eskgI2A+kXX5MBHgIEVmjHW5ssgDAx4S2eVd2NGS9EPgChK9QokFuPrqzvpPk9jv0mq8l7fHhm3FCspzJuQ2hOz6Yw8CiwJjqOg/Jy18sSsn381zAd6j//uz1qPRAoGAGV29/5ApxR7A4H1kqg46P/yXzIrKfEGMKgT9iRj7YAt2Z5Y4HlsHJnEtLQfhKgUu/KKCItY8X9G/kBmb+GSTpvDD+UPl3NmuK4XyaaW55y43ndlkwwB3X9TaDCnWCeFhsJmeES3ECk797EtyVF7EjZ94PG0lYvefzEXmhZxKGJUCgYBQqWaku95MIkn7KpJfWNEMgATPobFd2eQhONsEM+7THzuCqQxuSZPuFZGJMtBHwmHj13m5MUiL9rz1XJmybdA9UL5HOab2OSJGd2DanTLRz99bK5zo5rLIuZW2nRvscFH0H7lhS8sROykKz0yvyFO0Ww05vYQCD/Uvb/v2zZxTfQ==";
		String PUBLICKEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlY/b8e3us/uZA+NxJ8Wb3yGdvfUsGMWM4wICH8Hrvzre95kcwM1W2wrG1LlhmIKqTfaLc4x83t4RjsrOtUgPIQlIYOMrs5GbvwuxeaYDfQJFDoXEtqoDsrsJVp8Z/EMssmRpyAR9SbrmtFFIuqESiu4HjphlYl7qGFBqF9ay79k0C1Ujntb39++wZj5rYxaK0vDoBlidWzuc6PFeshhldoPHY9gNUPsW1Cj1bFPtMQlUqyWy1oCce2qSpF/hPcaIfCdNU94ROv5tUkkHj3A2bIzqMvdwngizWNLZsORfd4KcJTuC/qMRlUB1rZLunR1vE1T+7fQwFvlHA8LGlWjZOQIDAQAB";
		RSAPrivateKey privateKey = getPrivateKey(PRIVATEKEY);
		RSAPublicKey publicKey = getPublicKey(PUBLICKEY);
		String text = "123456789";
		String secret = privateEncrypt(text,privateKey);
		System.out.println(secret);
		System.out.println(publicDecrypt(secret,publicKey));
	}
}
