package com.malk.lianan.utils;

import cn.hutool.core.codec.Base64;
import com.malk.utils.UtilFile;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.jolokia.util.Base64Util;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Objects;

public class RsaUtil {

    private final static String KEY_RSA = "RSA";
    private final static String KEY_RSA_SIGNATURE = "SHA256WithRSA";
    private static BouncyCastleProvider bouncyCastleProvider = new BouncyCastleProvider();

    private static final String SHA256WithRSA = "SHA256WithRSA";
    private static final String X509 = "X.509";


    public static String sign(byte[] data, String privateKey) {
        String str = "";
        try {
            // 解密由 base64 编码的私钥
            byte[] bytes = decryptBase64(privateKey);
            // 构造 PKCS8EncodedKeySpec 对象
            PKCS8EncodedKeySpec pkcs = new PKCS8EncodedKeySpec(bytes);
            // 指定的加密算法
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA,bouncyCastleProvider);
            // 取私钥对象
            PrivateKey key = factory.generatePrivate(pkcs);
            // 用私钥对信息生成数字签名
            Signature signature =Signature.getInstance(KEY_RSA_SIGNATURE,bouncyCastleProvider);
            signature.initSign(key);
            signature.update(data);
            str = encryptBase64(signature.sign());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str;
    }

    //验签
    public static boolean verifySign(byte[] data, String sign, String certificatePath) throws Exception {
        // 获得证书
        // certificatePath 为 cer 证书文件绝对路径
        X509Certificate x509Certificate = (X509Certificate) getCertificate(certificatePath);
        if (Objects.isNull(x509Certificate)) {
            return false;
        }
        // 获得公钥
        PublicKey publicKey = x509Certificate.getPublicKey();
        // 构建签名
        Signature signature = Signature.getInstance(SHA256WithRSA);
        signature.initVerify(publicKey);
        signature.update(data);
        return signature.verify(Base64Util.decode(sign));
    }

    private static Certificate getCertificate(String certificatePath) throws Exception {
        InputStream in = null;
        try {
            CertificateFactory certificateFactory = CertificateFactory.getInstance(X509);
//            in = Files.newInputStream(Paths.get(certificatePath));

            in = UtilFile.readPackageResource(certificatePath);
            return certificateFactory.generateCertificate(in);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    System.out.println(e.getMessage());
                }
            }
        }
        return null;
    }

    public static Certificate loadCertificate(String relativePathInResources) throws Exception {
        // 使用 ClassLoader 获取资源流（路径以 / 开头表示从 classpath 根目录开始）
        try (InputStream in = RsaUtil.class.getClassLoader().getResourceAsStream(relativePathInResources)) {
            if (in == null) {
                throw new IllegalArgumentException("Certificate not found in resources: " + relativePathInResources);
            }
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            return certificateFactory.generateCertificate(in);
        }
    }

    public static byte[] decryptBase64(String key) throws Exception {
        return Base64.decode(key);
    }
    public static String encryptBase64(byte[] key) throws Exception {
        return new String(Base64.encode(key));
    }

}
