package cd.casic.ci.process.util;


// ... 省略 package 和 import ...
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.engines.SM4Engine;
import org.bouncycastle.crypto.generators.SM2KeyPairGenerator;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.*;
import org.bouncycastle.crypto.signers.SM2Signer;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;

import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.ECGenParameterSpec;

public class CryptogramUtil {

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * SM2 公钥加密
     */
    public static String doSm2Encrypt(String str) {
        try {
            byte[] data = str.getBytes(StandardCharsets.UTF_8);
            ECPublicKeyParameters pubKey = getSm2PublicKey(Keypair.PUBLIC_KEY);
            SM2Engine engine = new SM2Engine();
            engine.init(true, pubKey);
            byte[] enc = engine.processBlock(data, 0, data.length);
            return Hex.toHexString(enc);
        } catch (Exception e) {
            throw new RuntimeException("SM2加密失败", e);
        }
    }

    /**
     * SM2 私钥解密
     */
    public static String doSm2Decrypt(String str) {
        try {
            byte[] enc = Hex.decode(str);
            ECPrivateKeyParameters priKey = getSm2PrivateKey(Keypair.PRIVATE_KEY);
            SM2Engine engine = new SM2Engine();
            engine.init(false, priKey);
            byte[] dec = engine.processBlock(enc, 0, enc.length);
            return new String(dec, StandardCharsets.UTF_8);
        } catch (Exception e) {
            // 解密失败返回原文
            return str;
        }
    }

    /**
     * SM4 CBC 加密
     */
    public static String doEncrypt(String str) {
        try {
            byte[] key = Hex.decode(Keypair.KEY);
            byte[] iv = Hex.decode(Keypair.IV);
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new SM4Engine()));
            cipher.init(true, new ParametersWithIV(new KeyParameter(key), iv));
            byte[] input = str.getBytes(StandardCharsets.UTF_8);
            byte[] output = new byte[cipher.getOutputSize(input.length)];
            int len = cipher.processBytes(input, 0, input.length, output, 0);
            len += cipher.doFinal(output, len);
            return Hex.toHexString(output, 0, len);
        } catch (Exception e) {
            throw new RuntimeException("SM4加密失败", e);
        }
    }

    /**
     * SM4 CBC 解密
     */
    public static String doDecrypt(String str) {
        try {
            byte[] key = Hex.decode(Keypair.KEY);
            byte[] iv = Hex.decode(Keypair.IV);
            PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new SM4Engine()));
            cipher.init(false, new ParametersWithIV(new KeyParameter(key), iv));
            byte[] input = Hex.decode(str);
            byte[] output = new byte[cipher.getOutputSize(input.length)];
            int len = cipher.processBytes(input, 0, input.length, output, 0);
            len += cipher.doFinal(output, len);
            return new String(output, 0, len, StandardCharsets.UTF_8);
        } catch (Exception e) {
            // 解密失败返回原文
            return str;
        }
    }

    /**
     * SM2 签名
     */
    public static String doSignature(String str) {
        try {
            ECPrivateKeyParameters priKey = getSm2PrivateKey(Keypair.PRIVATE_KEY);
            SM2Signer signer = new SM2Signer();
            signer.init(true, priKey);
            byte[] msg = str.getBytes(StandardCharsets.UTF_8);
            signer.update(msg, 0, msg.length);
            byte[] sig = signer.generateSignature();
            return Hex.toHexString(sig);
        } catch (Exception e) {
            throw new RuntimeException("SM2签名失败", e);
        }
    }

    /**
     * SM2 验签
     */
    public static boolean doVerifySignature(String originalStr, String str) {
        try {
            ECPublicKeyParameters pubKey = getSm2PublicKey(Keypair.PUBLIC_KEY);
            SM2Signer signer = new SM2Signer();
            signer.init(false, pubKey);
            byte[] msg = originalStr.getBytes(StandardCharsets.UTF_8);
            signer.update(msg, 0, msg.length);
            byte[] sig = Hex.decode(str);
            return signer.verifySignature(sig);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * SM3 哈希
     */
    public static String doHashValue(String str) {
        try {
            SM3Digest digest = new SM3Digest();
            byte[] msg = str.getBytes(StandardCharsets.UTF_8);
            digest.update(msg, 0, msg.length);
            byte[] hash = new byte[digest.getDigestSize()];
            digest.doFinal(hash, 0);
            return Hex.toHexString(hash);
        } catch (Exception e) {
            throw new RuntimeException("SM3哈希失败", e);
        }
    }

    // ====== 工具方法 ======

    // 获取SM2公钥参数
    private static ECPublicKeyParameters getSm2PublicKey(String hex) {
        org.bouncycastle.jce.spec.ECParameterSpec ecSpec = org.bouncycastle.jce.ECNamedCurveTable.getParameterSpec("sm2p256v1");
        org.bouncycastle.math.ec.ECPoint q = ecSpec.getCurve().decodePoint(Hex.decode(hex));
        return new ECPublicKeyParameters(q, new ECDomainParameters(ecSpec.getCurve(), ecSpec.getG(), ecSpec.getN()));
    }

    // 获取SM2私钥参数
    private static ECPrivateKeyParameters getSm2PrivateKey(String hex) {
        org.bouncycastle.jce.spec.ECParameterSpec ecSpec = org.bouncycastle.jce.ECNamedCurveTable.getParameterSpec("sm2p256v1");
        return new ECPrivateKeyParameters(new java.math.BigInteger(hex, 16), new ECDomainParameters(ecSpec.getCurve(), ecSpec.getG(), ecSpec.getN()));
    }

    private static class Keypair {
        // 公钥（未压缩点，hex字符串，前缀04）
        public static final String PUBLIC_KEY = "04298364ec840088475eae92a591e01284d1abefcda348b47eb324bb521bb03b0b2a5bc393f6b71dabb8f15c99a0050818b56b23f31743b93df9cf8948f15ddb54";
        // 私钥（hex字符串）
        public static final String PRIVATE_KEY = "3037723d47292171677ec8bd7dc9af696c7472bc5f251b2cec07e65fdef22e25";
        // SM4密钥（16字节，128位，hex字符串）
        public static final String KEY = "0123456789abcdeffedcba9876543210";
        // SM4 IV（16字节，hex字符串）
        public static final String IV = "fedcba98765432100123456789abcdef";
    }
}
