package com.yeejoin.amos.boot.module.hygf.api.util;


import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.pkcs.RSAPrivateKeyStructure;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
import org.springframework.core.io.ClassPathResource;

/**
 * SHA256WithRSA签名、验签工具
 *
 * @FileName: RSASignUtils.java
 */
public class RSASignUtils {

    /**
     * 日志
     */


    private static final String SIGN_SHA256RSA_ALGORITHMS = "SHA256WithRSA";
    private static final String SIGN_SHA1RSA_ALGORITHMS = "SHA1WithRSA";

    /**
     * 签名
     *
     * @param content
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static String sign(String content, PrivateKey privateKey) throws Exception {
        Signature signature = Signature.getInstance(SIGN_SHA256RSA_ALGORITHMS);
        signature.initSign(privateKey);
        signature.update(content.getBytes(StandardCharsets.UTF_8));
        // 签名使用Base64编码后得到的值即为请求数据中signature字段的值
        return Base64.encodeBase64String(signature.sign());
    }

    public static String signWithByte(byte[] content, PrivateKey privateKey) throws Exception {
        Signature signature = Signature.getInstance(SIGN_SHA256RSA_ALGORITHMS);
        signature.initSign(privateKey);
        signature.update(content);
        // 签名使用Base64编码后得到的值即为请求数据中signature字段的值
        return Base64.encodeBase64String(signature.sign());
    }

    public static byte[] signWithByte_New(byte[] content, PrivateKey privateKey) throws Exception {
        Signature signature = Signature.getInstance(SIGN_SHA256RSA_ALGORITHMS);
        signature.initSign(privateKey);
        signature.update(content);
        // 签名使用Base64编码后得到的值即为请求数据中signature字段的值
        return signature.sign();
    }


    private static byte[] convertPKCS1ToPKCS8(byte[] pkcs1Bytes) throws Exception {
        // 使用 BouncyCastle 库解析 PKCS#1 格式的私钥
        RSAPrivateKeyStructure pkcs1PrivKey = RSAPrivateKeyStructure.getInstance(pkcs1Bytes);

        // 构建 AlgorithmIdentifier，指定了 rsaEncryption OID 和空参数
        AlgorithmIdentifier algId = new AlgorithmIdentifier(
                PKCSObjectIdentifiers.rsaEncryption,
                DERNull.INSTANCE
        );

        // 构建 PKCS#8 格式的私钥信息
        PrivateKeyInfo pkcs8PrivKeyInfo = new PrivateKeyInfo(algId, pkcs1PrivKey.toASN1Object());

        // 返回 PKCS#8 格式的编码字节数组
        return pkcs8PrivKeyInfo.getEncoded();
    }

    /**
     * 验签
     *
     * @param content
     * @param signature
     * @param publicKey
     * @return
     */
    public static Boolean checkSign(String content, String signature, PublicKey publicKey) {
        try {

            Signature signatureTool = Signature.getInstance(SIGN_SHA256RSA_ALGORITHMS);
            signatureTool.initVerify(publicKey);
            signatureTool.update(content.getBytes(StandardCharsets.UTF_8));
            byte[] signbyte = Base64.decodeBase64(signature.getBytes());
            return signatureTool.verify(signbyte);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public static Boolean checkSignWithBytes(byte[] src_Bytes, byte[] signBytes, PublicKey publicKey) {
        try {

            Signature signatureTool = Signature.getInstance(SIGN_SHA1RSA_ALGORITHMS);
            signatureTool.initVerify(publicKey);
            signatureTool.update(src_Bytes);
            byte[] signbyte = (signBytes);
            return signatureTool.verify(signbyte);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public static Boolean checkSignWithBytes256(byte[] src_Bytes, byte[] signBytes, PublicKey publicKey) {
        try {

            Signature signatureTool = Signature.getInstance(SIGN_SHA256RSA_ALGORITHMS);
            signatureTool.initVerify(publicKey);
            signatureTool.update(src_Bytes);
            byte[] signbyte = (signBytes);
            return signatureTool.verify(signbyte);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 加载 pkcs8 格式私钥
     *
     * @param path
     * @return
     * @throws Exception
     */
    public static PrivateKey loadPrivateKey(String path) throws Exception {
        ClassPathResource classPathResource = new ClassPathResource(path);

        PemReader pemReader = new PemReader(new InputStreamReader(classPathResource.getInputStream()));
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(pemReader.readPemObject().getContent());
        pemReader.close();
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(pkcs8EncodedKeySpec);
    }

    /**
     * 从证书加载公钥
     *
     * @param path
     * @return
     * @throws Exception
     */
    public static PublicKey loadPublicKey(String path) throws Exception {
        CertificateFactory fact = CertificateFactory.getInstance("X.509");
        FileInputStream is = new FileInputStream(path);
        X509Certificate cer = (X509Certificate) fact.generateCertificate(is);
        return cer.getPublicKey();
    }

    /**
     * 从指定路径加载并转换 PKCS#1 格式的 RSA 私钥为 PKCS#8 格式。
     *
     * @param path 私钥文件的路径。该文件应为 PEM 格式，并包含 PKCS#1 格式的 RSA 私钥信息。
     * @return 解析并转换后的 PrivateKey 对象，用于后续的加密或签名操作。
     * @throws Exception 如果读取文件、解析或转换私钥时发生错误。
     */
    public static PrivateKey loadPrivateKeyNew(String path) throws Exception {
        try (FileInputStream fis = new FileInputStream(path);
             InputStreamReader isr = new InputStreamReader(fis);
             PemReader pemReader = new PemReader(isr)) {

            // 读取 PEM 文件中的对象
            PemObject pemObject = pemReader.readPemObject();
            if (pemObject == null) {
                throw new IOException("PEM file is empty or not in the correct format: " + path);
            }

            // 获取编码后的私钥数据
            byte[] encoded = pemObject.getContent();

            // 将 PKCS#1 转换为 PKCS#8
            byte[] pkcs8Key = convertPKCS1ToPKCS8(encoded);

            // 创建 PKCS#8 编码规范
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(pkcs8Key);

            // 获取 RSA 算法的 KeyFactory 实例，用于生成私钥对象
            KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC");

            // 使用 KeyFactory 和 PKCS#8 编码规范来生成并返回 PrivateKey 对象
            return keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        } catch (IOException e) {
            throw new IOException("Error reading private key from file: " + path, e);
        } catch (Exception e) {
            throw new Exception("Unexpected error while loading private key from file: " + path, e);
        }
    }

    /**
     * 从文件加载 PKCS8 格式的 RSA 公钥
     */
    public static RSAPublicKey readPublicKeyFromFile(String path) throws Exception {
        String publicKeyPEM = "-----BEGIN PUBLIC KEY-----\n" +
                "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwFgHD4kzEVPdOj03ctKM7KV+1\n" +
                "6bWZ5BMNgvEeuEQwfQYkRVwI9HFOGkwNTMn5hiJXHnlXYCX+zp5r6R52MY0O7BsT\n" +
                "CLT7aHaxsANsvI9ABGx3OaTVlPB59M6GPbJh0uXvio0m1r/lTW3Z60RU6Q3oid/r\n" +
                "NhP3CiNgg0W6O3AGqwIDAQAB\n" +
                "-----END PUBLIC KEY-----";
        publicKeyPEM = publicKeyPEM.replace("-----BEGIN PUBLIC KEY-----", "")
                .replace("-----END PUBLIC KEY-----", "")
                .replaceAll("\\r", "").replaceAll("\\n", "");

        byte[] publicKeyDER = java.util.Base64.getDecoder().decode(publicKeyPEM);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return (RSAPublicKey) keyFactory.generatePublic(new X509EncodedKeySpec(publicKeyDER));
    }


    public static void main(String[] args) throws Exception {

//        FileUtils.save2File(
//                "/Users/cyzx-mengxr/Downloads/00008_0202202280000000579_0200003309088104357_001_20220930_acc_1_1_New.sign",
//                RSASignUtils.signWithByte_New( FileUtils.toByteArray("/Users/cyzx-mengxr/Downloads/00008_0202202280000000579_0200003309088104357_001_20220930_acc_1_1.zip"),
//                RSASignUtils .loadPrivateKey("/Users/cyzx-mengxr/Downloads/private.pem")));


        //String signSrc = RSAUtil.byte2Hex(FileUtils.toByteArray("/Users/cyzx-mengxr/Downloads/00008_0202202280000000579_0200003309088104357_001_20220930_acc_1_1.sign"));
        //String signSrc = RSAUtil(FileUtils.toByteArray("/Users/cyzx-mengxr/Downloads/00008_0202202280000000579_0200003309088104357_001_20220930_acc_1_1.sign"));
        /*验证网关文件*/

//        System.out.println( RSASignUtils.checkSignWithBytes(
//                FileUtils.toByteArray("/Users/cyzx-mengxr/Downloads/00008_0202202280000000579_0200003309088104357_001_20220930_acc_1_1.zip"),
//                FileUtils.toByteArray("/Users/cyzx-mengxr/Downloads/00008_0202202280000000579_0200003309088104357_001_20220930_acc_1_1.sign"),
//                RSASignUtils.readPublicKeyFromFile("/Users/cyzx-mengxr/Downloads/public.pem")));


        System.out.println(RSASignUtils.checkSignWithBytes256(
                FileUtils.toByteArray("/Users/cyzx-mengxr/Library/Containers/com.tencent.xinWeChat/Data/Library/Application Support/com.tencent.xinWeChat/2.0b4.0.9/dc1430eae477f5ad06811d277af61ff6/Message/MessageTemp/bb418fb928671a5accdc29aba40c4b42/File/ENTRUSTRES-20240331JB00400003.bin"),
                FileUtils.toByteArray("/Users/cyzx-mengxr/Library/Containers/com.tencent.xinWeChat/Data/Library/Application Support/com.tencent.xinWeChat/2.0b4.0.9/dc1430eae477f5ad06811d277af61ff6/Message/MessageTemp/bb418fb928671a5accdc29aba40c4b42/File/ENTRUSTRES-20240331JB00400003.sign"),
                RSASignUtils.readPublicKeyFromFile("/Users/cyzx-mengxr/Downloads/public.pem")));

    }
}