package org.fouram.core.util;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

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

import sun.misc.BASE64Decoder;

@SuppressWarnings("restriction")
public class RSAOperator {
	public static final String KEY_ALGORITHM = "RSA";
	public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
	public static String str_pubKey_api = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdUCId49MryzBKwc7tEp7eWmAy"
			+ "ZTsLuVRoPUEHLQT8NV+L51Tg9bbmSNKT8KiYw/nJqA2BJZ3h+vF5jhVInJrG1OfI"
			+ "ydGoJBv9/N6oQ8GH0L+78+dxtBsVJEjdTBjSm4yBjHTmyLHYBag4ExylgXzO+Nu9"
			+ "laFbcQa6bYr+0XaQAQIDAQAB";
	public static String str_priKey_pkcs8_api = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAN1QIh3j0yvLMErB"
			+ "zu0Snt5aYDJlOwu5VGg9QQctBPw1X4vnVOD1tuZI0pPwqJjD+cmoDYElneH68XmO"
			+ "FUicmsbU58jJ0agkG/383qhDwYfQv7vz53G0GxUkSN1MGNKbjIGMdObIsdgFqDgT"
			+ "HKWBfM74272VoVtxBrptiv7RdpABAgMBAAECgYEAkdNOV6GZsH6XGHsxzNZ7Jgoo"
			+ "3qwDRwtcCb9qzL6mTUUh6v6H2B8v3/dWAbMOdHKVcYGxPEq8CH4ghLbRYWIHPQg/"
			+ "w5YWes104B2dDhKbnkad93Zf/GbSmizTBAq+kZn/mjYdC1DSMKfVXdE8edePkawR"
			+ "ix1JjGjgDRVKbI/z4NECQQD7crKyT2Cxkf7gBqiBoiICNeepjY5V+7Uq1n0nQv6m"
			+ "emOeLJx4cBf7n8mywKQeNyMZCo44+xQxY17Ao8k9gr4tAkEA4VHHT+Rl+nPEoihM"
			+ "lyybRbl/d4WUq9F7yAWRsBGTqvvun/4GQgUkinNkEEdbWVDwix/vVnTctZcHDzDQ"
			+ "v3URpQJBAMonV5VVjeaU+rV/hN/byr2+OsatAN8N44RSNwJmsTaEtSxIr2+Apzds"
			+ "Koukpw2HxJbwTpFvArgGLPpxc2wZfe0CQHFj607cXSm2Gu2UJD8r1pQ3LtuiYNg6"
			+ "2vUlQFT/83VnxYXEm7ebyPDX8zJyBpmjLvqEvriepPfJombVpSfErXUCQQD0BcYa"
			+ "zJ+dD8aM+z6kFMrsiNmq9SDO7gxULyfnSfqjCmD8hQ2uy9GddWMoDzNr4MI/9vZw"
			+ "ujwiynaz3PwaL1au";
	public static String str_pubKey_huiyuan = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdUCId49MryzBKwc7tEp7eWmAy"
			+ "ZTsLuVRoPUEHLQT8NV+L51Tg9bbmSNKT8KiYw/nJqA2BJZ3h+vF5jhVInJrG1OfI"
			+ "ydGoJBv9/N6oQ8GH0L+78+dxtBsVJEjdTBjSm4yBjHTmyLHYBag4ExylgXzO+Nu9"
			+ "laFbcQa6bYr+0XaQAQIDAQAB";
	public static String str_priKey_pkcs8_huiyuan = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAN1QIh3j0yvLMErB"
			+ "zu0Snt5aYDJlOwu5VGg9QQctBPw1X4vnVOD1tuZI0pPwqJjD+cmoDYElneH68XmO"
			+ "FUicmsbU58jJ0agkG/383qhDwYfQv7vz53G0GxUkSN1MGNKbjIGMdObIsdgFqDgT"
			+ "HKWBfM74272VoVtxBrptiv7RdpABAgMBAAECgYEAkdNOV6GZsH6XGHsxzNZ7Jgoo"
			+ "3qwDRwtcCb9qzL6mTUUh6v6H2B8v3/dWAbMOdHKVcYGxPEq8CH4ghLbRYWIHPQg/"
			+ "w5YWes104B2dDhKbnkad93Zf/GbSmizTBAq+kZn/mjYdC1DSMKfVXdE8edePkawR"
			+ "ix1JjGjgDRVKbI/z4NECQQD7crKyT2Cxkf7gBqiBoiICNeepjY5V+7Uq1n0nQv6m"
			+ "emOeLJx4cBf7n8mywKQeNyMZCo44+xQxY17Ao8k9gr4tAkEA4VHHT+Rl+nPEoihM"
			+ "lyybRbl/d4WUq9F7yAWRsBGTqvvun/4GQgUkinNkEEdbWVDwix/vVnTctZcHDzDQ"
			+ "v3URpQJBAMonV5VVjeaU+rV/hN/byr2+OsatAN8N44RSNwJmsTaEtSxIr2+Apzds"
			+ "Koukpw2HxJbwTpFvArgGLPpxc2wZfe0CQHFj607cXSm2Gu2UJD8r1pQ3LtuiYNg6"
			+ "2vUlQFT/83VnxYXEm7ebyPDX8zJyBpmjLvqEvriepPfJombVpSfErXUCQQD0BcYa"
			+ "zJ+dD8aM+z6kFMrsiNmq9SDO7gxULyfnSfqjCmD8hQ2uy9GddWMoDzNr4MI/9vZw"
			+ "ujwiynaz3PwaL1au";

	/**
	 * 使用getPublicKey得到公钥,返回类型为PublicKey
	 * 
	 * @param base64
	 *            String to PublicKey
	 * @throws Exception
	 */
	public static PublicKey getPublicKey(String key) throws Exception {
		byte[] keyBytes;
		keyBytes = (new BASE64Decoder()).decodeBuffer(key);
		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PublicKey publicKey = keyFactory.generatePublic(keySpec);
		return publicKey;
	}

	/**
	 * 转换私钥
	 * 
	 * @param base64
	 *            String to PrivateKey
	 * @throws Exception
	 */
	public static PrivateKey getPrivateKey(String key) throws Exception {
		byte[] keyBytes;
		keyBytes = (new BASE64Decoder()).decodeBuffer(key);
		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
		return privateKey;
	}

	// ***************************签名和验证*******************************
	public static byte[] sign(byte[] data) throws Exception {
		PrivateKey priK = getPrivateKey(str_priKey_pkcs8_api);
		Signature sig = Signature.getInstance(SIGNATURE_ALGORITHM);
		sig.initSign(priK);
		sig.update(data);
		return sig.sign();
	}

	public static boolean verify(byte[] data, byte[] sign) throws Exception {
		PublicKey pubK = getPublicKey(str_pubKey_api);
		Signature sig = Signature.getInstance(SIGNATURE_ALGORITHM);
		sig.initVerify(pubK);
		sig.update(data);
		return sig.verify(sign);
	}

	// ************************公钥加密私钥解密**************************
	public static byte[] encryptPubKey(byte[] bt_plaintext) throws Exception {
		PublicKey publicKey = getPublicKey(str_pubKey_api);
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.ENCRYPT_MODE, publicKey);
		byte[] bt_encrypted = cipher.doFinal(bt_plaintext);
		return bt_encrypted;
	}

	public static byte[] decryptPriKey(byte[] bt_encrypted) throws Exception {
		PrivateKey privateKey = getPrivateKey(str_priKey_pkcs8_api);
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.DECRYPT_MODE, privateKey);
		byte[] bt_original = cipher.doFinal(bt_encrypted);
		return bt_original;
	}

	// ************************私钥加密公钥解密**************************
	public static byte[] encryptPriKey(byte[] bt_plaintext) throws Exception {
		PrivateKey privateKey = getPrivateKey(str_priKey_pkcs8_huiyuan);
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.ENCRYPT_MODE, privateKey);
		byte[] bt_encrypted = cipher.doFinal(bt_plaintext);
		return bt_encrypted;
	}

	public static byte[] decryptPubKey(byte[] bt_encrypted) throws Exception {
		PublicKey publicKey = getPublicKey(str_pubKey_huiyuan);
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.DECRYPT_MODE, publicKey);
		byte[] bt_original = cipher.doFinal(bt_encrypted);
		return bt_original;
	}

	// ********************main函数：加密解密和签名验证*********************
	public static void main(String[] args) throws Exception {
		String str_plaintext = "xianwallet201704";
		System.err.println("明文:" + str_plaintext);
		byte[] bt_cipher = encryptPubKey(str_plaintext.getBytes());
		String cont = Base64.encodeBase64String(bt_cipher);
		System.out.println("加密:" + cont);
		byte[] bt_original = decryptPriKey(Base64.decodeBase64(cont));
		String str_original = new String(bt_original);
		System.out.println("解密:" + str_original);

		String ccc = "Czm0gQLvkbV+6S1PczVntBQf76Z5fpBnChDRVMP8XAVCyzrSbSEU8+/2os/HdV1/sm7kkn1NS8wrjSoU2fKo4ZR7H5WoH/5jE/w6Azhvxd3oIJDY3/EY/rYAQ0xzh9MguQqLwkV8rFU143aE8EYYVRNDhJgh64KkLEh4BxX/HV0=";
		bt_original = decryptPriKey(Base64.decodeBase64(ccc));
		str_original = new String(bt_original);
		System.out.println("解密:" + str_original);
	}

}