using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;

namespace CrazyStudio.Core.Common.Tools
{
    public class SM2Tool
    {
        /// <summary>
        /// 生成 SM2 密钥对，密钥对使用 Base64 进行编码
        /// </summary>
        /// <param name="privateKey"></param>
        /// <param name="publicKey"></param>
        public static void GenerateSM2KeyPair(out string privateKey, out string publicKey)
        {
            // 获取 SM2 曲线参数
            X9ECParameters curve = ECNamedCurveTable.GetByName("sm2p256v1");
            KeyGenerationParameters parameters = new ECKeyGenerationParameters(new ECDomainParameters(curve), new SecureRandom());

            // 创建 SM2 密钥对生成器
            ECKeyPairGenerator generator = new ECKeyPairGenerator();
            generator.Init(parameters);

            // 创建密钥对
            var keyPair = generator.GenerateKeyPair();

            // 私钥
            ECPrivateKeyParameters privateKeyParameters = (ECPrivateKeyParameters)keyPair.Private;
            privateKey = Base64.ToBase64String(privateKeyParameters.D.ToByteArrayUnsigned());

            // 公钥
            ECPublicKeyParameters publicKeyParameters = (ECPublicKeyParameters)keyPair.Public;
            publicKey = Base64.ToBase64String(publicKeyParameters.Q.GetEncoded());
        }

        /// <summary>
        /// SM2 公钥加密
        /// </summary>
        /// <param name="message"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string Encrypt(string message, string key)
        {
            // 获取 SM2 曲线参数
            X9ECParameters curve = ECNamedCurveTable.GetByName("sm2p256v1");

            var q = curve.Curve.DecodePoint(Base64.Decode(key));
            ECDomainParameters domain = new ECDomainParameters(curve);
            ECPublicKeyParameters pubk = new ECPublicKeyParameters("EC", q, domain);

            // 创建SM2加密器
            SM2Engine sm2Engine = new SM2Engine();
            sm2Engine.Init(true, new ParametersWithRandom(pubk, new SecureRandom()));

            // 将原始数据转换为字节数组
            byte[] dataBytes = Encoding.UTF8.GetBytes(message);

            // 执行加密操作
            byte[] encryptedData = sm2Engine.ProcessBlock(dataBytes, 0, dataBytes.Length);

            // 将加密结果转换为 Base64 字符串
            return Base64.ToBase64String(encryptedData);
        }

        /// <summary>
        /// SM2 私钥解密
        /// </summary>
        /// <param name="message"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string Decrypt(string message, string key)
        {
            // 获取 SM2 曲线参数
            X9ECParameters curve = ECNamedCurveTable.GetByName("sm2p256v1");

            ECDomainParameters domain = new ECDomainParameters(curve);
            var d = new BigInteger(1, Base64.Decode(key));
            ECPrivateKeyParameters prik = new ECPrivateKeyParameters(d, domain);

            // 创建SM2加密器
            SM2Engine sm2Engine = new SM2Engine();
            sm2Engine.Init(false, prik);

            byte[] encryptedData = Base64.Decode(message);

            // 执行解密操作
            byte[] decryptedData = sm2Engine.ProcessBlock(encryptedData, 0, encryptedData.Length);

            // 将解密结果转换为字符串
            return Encoding.UTF8.GetString(decryptedData);
        }

    }
}
