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

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

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.security.cert.CertificateException;
import java.util.Enumeration;

/**
 * @author zengjunlin
 * @version 1.0
 * 2018-12-26 14:58
 */
public class Demo {

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

    /**
     * 签名算法
     * @param data    需要签名的内容
     * @return
     */
    public static String signData(String data) {
        KeyStore keyStore;
        byte[] signRstByte=null;
        String signValue="";
        try {
            keyStore = KeyStore.getInstance("PKCS12");//获取pfx证书实例    当证书为jks 格式时参数应当为JKS
            Thread.currentThread().getContextClassLoader();
            InputStream instream = new FileInputStream(CommonWxGlobalPayPropertiesBuilder.instance().getCertName());//含私钥的文件，获取证书文件流
            try {
                keyStore.load(instream, CommonWxGlobalPayPropertiesBuilder.instance().getMchId().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, CommonWxGlobalPayPropertiesBuilder.instance().getMchId().toCharArray());//从证书中获取私钥
            System.out.println("private key:\n" + privateKey);
            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);//SHA256withRSA签名算法
            signature.initSign(privateKey);//设置私钥
            signature.update(data.getBytes( ENCODING));//设置明文
            signRstByte = signature.sign();//加密
            signValue= encodeBase64(signRstByte);//BASE64编码
            System.out.println("签名并编码后的内容signValue=="+signValue);
        } 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();
        }
        return signValue;
    }
    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;
    }
}
