package nckd.jimin.jyyy.bd.common.oauth;

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

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class SSORSAUtils {

    private static Provider provider;

    static {
        provider = new org.bouncycastle.jce.provider.BouncyCastleProvider();
        Security.addProvider(provider);
    }

    /**
     * 产生key pair，提供provider和random
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
        // 产生用于安全加密的随机数
        SecureRandom random = new SecureRandom();

        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", provider);
        Integer length = 2048;//加密算法位数
        generator.initialize(length, random);
        return generator.generateKeyPair();
    }

    /**
     * 返回一个keyBytes生成的PublicKey对象
     * @param keyBytes
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     */
    public static PublicKey getPublicKey(byte[] keyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
    }

    public static byte[] encryptByKey(Key keys, byte[] byteArray) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        // Cipher: 提供加密和解密功能的实例
        // transformation: "algorithm/mode/padding"
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);
        // PrivateKey privateKey = keyPair.getPrivate();
        // 初始化
        cipher.init(Cipher.ENCRYPT_MODE, keys);
        // doFinal(): 加密或者解密数据
        byte[] plainText = cipher.doFinal(byteArray);
        return plainText;
    }

    /**
     * 返回一个keyBytes生成的privateKey对象
     * @param keyBytes
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     */
    public static PrivateKey getPrivateKey(byte[] keyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }

    /**
     * 用相应的key解密对应加密的问题
     *
     * @param keys
     * @param byteArray
     * @return
     */
    public static byte[] decryptByKey(Key keys, byte[] byteArray) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        // Cipher: 提供加密和解密功能的实例
        // transformation: "algorithm/mode/padding"
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);

        // 初始化
        cipher.init(Cipher.DECRYPT_MODE, keys);
        // doFinal(): 加密或者解密数据
        byte[] plainText = cipher.doFinal(byteArray);

//        byte[] bytes = processData(cipher, byteArray, 1024 / 8);

        return plainText;
    }

    /**
     * 分段处理数据.
     *
     * @param cipher      密码算法
     * @param dataes      数据
     * @param segmentSize 分段大小（小于等于0不分段）
     * @return
     */
    private static byte[] processData(Cipher cipher, byte[] dataes, int segmentSize) {
        byte[] decBytes = null;
        try {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int inputLength = dataes.length;
            int offSet = 0;
            for (int i = 0; inputLength - offSet > 0; offSet = i * segmentSize) {
                byte[] cache;
                if (inputLength - offSet > segmentSize) {
                    cache = cipher.doFinal(dataes, offSet, segmentSize);
                } else {
                    cache = cipher.doFinal(dataes, offSet, inputLength - offSet);
                }
                out.write(cache, 0, cache.length);
                ++i;
            }
            decBytes = out.toByteArray();
            out.close();
        } catch (Exception e) {
        }
        return decBytes;
    }

    /**
     * 产生public key
     *
     * @return public key字符串
     */
    public static String generateBase64Key(byte[] keys) {
        // encodeBase64(): Encodes binary data using the base64
        // algorithm but does not chunk the output.
        // getEncoded():返回key的原始编码形式
        return new String(Base64.encodeBase64(keys));
    }
}