package com.kmall.common.utils.wechat.wxglobal;

import java.io.*;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.spec.InvalidKeySpecException;
import java.util.Enumeration;

import com.kmall.common.service.pay.global.CommonWxGlobalPayPropertiesBuilder;
import org.apache.commons.codec.binary.Base64;

/**
 * @author huangyq
 * @version 1.0
 * 2018-12-26 14:39
 */
public class SignUtil {

    private static final String ENCODING = "UTF-8";
    private static final String SIGNATURE_ALGORITHM = "SHA256withRSA";


    /**
     * 签名算法
     * @param data    需要签名的内容
     * @return
     */
    public static String signData(String data,String certName,String password) {
        KeyStore keyStore;
        byte[] signRstByte=null;
        String signValue="";
        try {
            keyStore = KeyStore.getInstance("PKCS12");//获取pfx证书实例    当证书为jks 格式时参数应当为JKS
            Thread.currentThread().getContextClassLoader();
            InputStream instream = new FileInputStream(certName);//含私钥的文件，获取证书文件流
            try {
                keyStore.load(instream, password.toCharArray());//加载证书到keystore中,商户id为含私钥文件的密码
            }finally {
                instream.close();
            }
            Enumeration enumas = keyStore.aliases();
            //此处不知道别名。（如有固定别名则直接用）
            String keyAlias = null;
            if (enumas.hasMoreElements()){
                keyAlias = (String)enumas.nextElement();
            }
            PrivateKey privateKey= (PrivateKey) keyStore.getKey(keyAlias, password.toCharArray());//从证书中获取私钥

            signRstByte = sign256(data,privateKey);//加密

            signValue= encodeBase64(signRstByte);//BASE64编码
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (UnrecoverableKeyException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (SignatureException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
        return signValue;
    }

    /**
     * SHA256WithRSA签名
     * @param data
     * @param privateKey
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     * @throws InvalidKeyException
     * @throws SignatureException
     * @throws UnsupportedEncodingException
     */
    public static byte[] sign256(String data, PrivateKey privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException,
            SignatureException, UnsupportedEncodingException {

        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);//SHA256withRSA签名算法

        signature.initSign(privateKey);//设置私钥

        signature.update(data.getBytes(ENCODING));//设置明文

        return signature.sign();//加密
    }

    public static boolean verify256(String data, byte[] sign, PublicKey publicKey){
        if(data == null || sign == null || publicKey == null){
            return false;
        }
        try {
            Signature signetcheck = Signature.getInstance(SIGNATURE_ALGORITHM);
            signetcheck.initVerify(publicKey);
            signetcheck.update(data.getBytes("UTF-8"));
            return signetcheck.verify(sign);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 二进制数据编码为BASE64字符串
     * @param bytes
     * @return
     */
    public static String encodeBase64(byte[] bytes){
        return new String(Base64.encodeBase64(bytes));
    }

    /**
     * BASE64解码
     * @param bytes
     * @return
     */
    public static byte[] decodeBase64(byte[] bytes) {
        byte[] result = null;
        try {
            result = Base64.decodeBase64(bytes);
        } catch (Exception e) {
            return null;
        }
        return result;
    }
}
