首页 > 编程语言 >C#SM2加密算法

C#SM2加密算法

时间:2023-08-16 14:57:26浏览次数:43  
标签:ecc string C# SM2 new byte pubKey public 加密算法

1.新建SM2Util类
    public class SM2Util
    {
        /**
           * 生成SM2秘钥对
           * string[0] 公钥
           * string[1] 私钥
           */
        public static string[] GenerateKeyPair()
        {
            return SM2.GenerateKeyPair();
        }

        /**
         * SM2签名
         * data 签名的数据
         * priKey 私钥
         */
        public static string Sign(string data, string priKey)
        {
            SM2 sm2 = new SM2(priKey, null);
            return sm2.Sign(data);

        }


        /**
         * SM2签名
         * sign 源数据
         * pubKey 公钥
         * sign 签名的数据
         */
        public static bool verifySign(string msg, string pubKey, string sign)
        {
            SM2 sm2 = new SM2(null, pubKey);
            return sm2.verifySign(msg, sign);
        }


        /**
         * 加密
         * 返回Base64字符串
         *  公钥加密
         *  plainText 要加密的文本
         *  pubKey 公钥
         */
        public static string encryptBase64(string plainText, string pubKey)
        {
            SM2 sm2 = new SM2(null, pubKey);
            byte[] encryptByte = sm2.encrypt(Encoding.UTF8.GetBytes(plainText));
            return Base64.ToBase64String(encryptByte);
        }

        /**
         * 解密
         *  私钥解密
         *  plainText 要加密的文本
         *  pubKey 公钥
         */
        public static string decryptBase64(string plainText, string priKey)
        {
            SM2 sm2 = new SM2(priKey, null);
            byte[] deCode = Base64.Decode(plainText);
            byte[] decryptText = sm2.deceypt(deCode);
            return Encoding.UTF8.GetString(decryptText);
        }
    }
2.新建SM2类
class SM2
    {

        private ECPrivateKeyParameters privateKeyParameters;


        private ECPublicKeyParameters publicKeyParameters;

        private SM2Param sm2Param;

        public SM2(string priKey, string pubKey)
        {
            this.init(HexUtils.decode(priKey), HexUtils.decode(pubKey));
        }

        private void init(byte[] priKey, byte[] pubKey)
        {
            this.sm2Param = new SM2Param();
            if (null != priKey && this.privateKeyParameters == null)
            {
                this.privateKeyParameters = new ECPrivateKeyParameters(new BigInteger(1, priKey), this.sm2Param.ecc_bc_spec);
            }
            if (null != pubKey && this.publicKeyParameters == null)
            {
                this.publicKeyParameters = new ECPublicKeyParameters(this.sm2Param.ecc_curve.DecodePoint(pubKey), this.sm2Param.ecc_bc_spec);

            }
        }


        /**
         * 加签
         */
        public string Sign(string data)
        {
            byte[] msg = Encoding.UTF8.GetBytes(data);
            SM2Signer sm2Signer = new SM2Signer();
            sm2Signer.Init(true, this.privateKeyParameters);
            sm2Signer.BlockUpdate(msg, 0, msg.Length);
            return Base64.ToBase64String(sm2Signer.GenerateSignature());
        }


        /*
         * 验签
         */
        public bool verifySign(string data, string sign)
        {
            byte[] signBase64 = Base64.Decode(sign);
            byte[] msgByte = Encoding.UTF8.GetBytes(data);
            SM2Signer sm2Signer = new SM2Signer();
            sm2Signer.Init(false, this.publicKeyParameters);
            sm2Signer.BlockUpdate(msgByte, 0, msgByte.Length);
            return sm2Signer.VerifySignature(signBase64);
        }

        /**
         * 加密
         * 
         */
        public byte[] encrypt(byte[] plainText)
        {
            SM2Engine engine = new SM2Engine();
            engine.Init(true, new ParametersWithRandom(this.publicKeyParameters));
            return engine.ProcessBlock(plainText, 0, plainText.Length);
        }
    

        /**
         * 
         * 解密
         * 
         */
        public byte[] deceypt(byte[] plainText)
        {
            byte[] plain = plainText;
            SM2Engine engine = new SM2Engine();
            engine.Init(false, this.privateKeyParameters);
            return engine.ProcessBlock(plain, 0, plain.Length);
        }


        public static string[] GenerateKeyPair()
        {
            AsymmetricCipherKeyPair kPair = genCipherKeyPair();
            ECPrivateKeyParameters ecPrivateKey = (ECPrivateKeyParameters)kPair.Private;
            ECPublicKeyParameters ecPublicKey = (ECPublicKeyParameters)kPair.Public;
            BigInteger priKey = ecPrivateKey.D;
            ECPoint pubKey = ecPublicKey.Q;
            byte[] priByte = priKey.ToByteArray();
            byte[] pubByte = pubKey.GetEncoded(false);
            if (priByte.Length == 33)
            {
                Console.WriteLine("private key size 33");
                byte[] newPriByte = new byte[32];
                Array.Copy(priByte, 1, newPriByte, 0, 32);
                priByte = newPriByte;
            }
            string[] keyPairs = new string[] { Hex.ToHexString(pubByte), Hex.ToHexString(priByte) };
            return keyPairs;
        }


        /**
         *      生成引用
         * */
        private static AsymmetricCipherKeyPair genCipherKeyPair()
        {
            SM2Param ecc_param = new SM2Param();
            ECDomainParameters ecDomainParamters = ecc_param.ecc_bc_spec;
            ECKeyGenerationParameters ecGenParam = new ECKeyGenerationParameters(ecDomainParamters, new SecureRandom());

            ECKeyPairGenerator ecKeyPairGenerator = new ECKeyPairGenerator();
            ecKeyPairGenerator.Init(ecGenParam);
            return ecKeyPairGenerator.GenerateKeyPair();
        }

        private class SM2Param
        {
            public static String[] ecc_param = { "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0" };
            public BigInteger ecc_p;
            public BigInteger ecc_a;
            public BigInteger ecc_b;
            public BigInteger ecc_n;
            public BigInteger ecc_gx;
            public BigInteger ecc_gy;
            public ECCurve ecc_curve;
            public ECDomainParameters ecc_bc_spec;

            public SM2Param()
            {
                this.ecc_p = new BigInteger(ecc_param[0], 16);
                this.ecc_a = new BigInteger(ecc_param[1], 16);
                this.ecc_b = new BigInteger(ecc_param[2], 16);
                this.ecc_n = new BigInteger(ecc_param[3], 16);
                this.ecc_gx = new BigInteger(ecc_param[4], 16);
                this.ecc_gy = new BigInteger(ecc_param[5], 16);
                this.ecc_curve = new FpCurve(ecc_p, ecc_a, ecc_b, ecc_n, BigInteger.One);
                this.ecc_bc_spec = new ECDomainParameters(this.ecc_curve, this.ecc_curve.CreatePoint(this.ecc_gx, this.ecc_gy), this.ecc_n);
            }
        }
    }
3.新建HexUtils
class HexUtils
    {
        private const string pattern = "^[a-f0-9]+$";

        public static bool isHex(string value)
        {
            if (null == value)
            {
                return false;
            }
            return System.Text.RegularExpressions.Regex.IsMatch(value, pattern);
        }

        public static byte[] decode(String str)
        {
            if (null == str)
            {
                return null;
            }
            if (isHex(str))
            {
                return hexStrToByte(str);
            }
            return Org.BouncyCastle.Utilities.Encoders.Base64.Decode(str);
        }

        public static byte[] hexStrToByte(String hexStr)
        {
            if ((null == hexStr) || (hexStr.Length == 0))
            {
                return null;
            }
            char[] hexData = hexStr.ToCharArray();
            int len = hexData.Length;
            if ((len & 0x1) != 0)
            {
                throw new SystemException("Odd number of characters.");
            }
            byte[] out1 = new byte[len >> 1];

            int i = 0;
            for (int j = 0; j < len; i++)
            {
                int f = toDigit(hexData[j], j) << 4;
                j++;
                f |= toDigit(hexData[j], j);
                j++;
                out1[i] = ((byte)(f & 0xFF));
            }
            return out1;
        }

        private static int toDigit(char ch, int index)
        {
            int digit = Convert.ToInt32(ch.ToString(), 16);
            //int digit = Character.digit(ch, 16);
            if (digit == -1)
            {
                throw new SystemException("Illegal hexadecimal character " + ch + " at index " + index);
            }
            return digit;
        }
    }
4.主函数
static void Main(string[] args)
        {
            String pubKey = "045b50327b39fe34374deeeaf44c1ed0f0bd7e20850c67ade650afdec125809fd8e499d3305d239864ef57af9218b490f204c33af1c31fd4a101d4989d579ec047";
            String priKey = "4e643581e15cbfecbfbb57b401a7eae91b9aa1073561b20606f28a03df16eec2";
            Console.WriteLine("公钥:" + pubKey);
            Console.WriteLine("私钥:" + priKey);

            Console.WriteLine("============================");

            String input = "POST|/api/v1.0/payment/pay-result-query|1627787104425|{\"payCode\":\"CK000000000011222324470415459\"}";
            Console.WriteLine("input:" + input);

            String sign = SM2Util.Sign(input, priKey);
            Console.WriteLine("sign:" + sign);

            Boolean success = SM2Util.verifySign(input, pubKey, sign);
            Console.WriteLine("success:" + success);


            Console.WriteLine("============================");

            String input2 = "湘A88888";
            String encrypt = SM2Util.encryptBase64(input2, pubKey);
            Console.WriteLine("encrypt:" + encrypt);

            String decrypt = SM2Util.decryptBase64(encrypt, priKey);
            Console.WriteLine("decrypt:" + decrypt);

        }
5.引入BouncyCastle.Crypto.dll动态库   注意动态库不同版本加密代码不一样*****
BouncyCastle.Crypto.dll动态库下载 https://files.cnblogs.com/files/ywtssydm/BouncyCastle.Crypto.rar?t=1692167684&download=true
完整代码下载: https://files.cnblogs.com/files/ywtssydm/CSharpDemo.zip?t=1692168492&download=true
更多资料:https://blog.csdn.net/a497785609/article/details/129102042
完整代码下载2:https://files.cnblogs.com/files/ywtssydm/sm2.rar?t=1692168765&download=true

 

标签:ecc,string,C#,SM2,new,byte,pubKey,public,加密算法
From: https://www.cnblogs.com/ywtssydm/p/17634122.html

相关文章

  • C# Modbus寄存器类
    注意:字节数据转换的时候用到了BitConverter扩展类,请参考我之前的文章 链接:https://www.cnblogs.com/smartnn/p/17633877.htmlusingModbus.Data;usingModbus.Device;usingModbus.Message;usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSys......
  • ZS Shuffles Cards 题解
    ZSShufflesCards题解我们把每一次抽一些数字牌再抽到joker视作一局游戏。每局期望轮数首先考虑\(f_i\)表示每一局游戏抽出\(i\)张牌的概率。那么就是先抽出\(i-1\)张数字牌,再抽出一张joker。概率就是:\[f_i=\fracm{n+m-i+1}\prod_{k=0}^{i-2}......
  • TZC-400学习
    ARM®CoreLink™TZC-400TrustZone®AddressSpaceController该篇文档的翻译及一些总结说明:https://www.cnblogs.com/lvzh/p/16582717.htmlTZC400学习总结这是个大佬的总结:https://blog.csdn.net/weixin_42135087/article/details/107161137TZC400总结之于SOC安全域https......
  • 知识图谱(Knowledge Graph)- Neo4j 5.10.0 使用 - CQL
    删除数据库中以往的图MATCH(n)DETACHDELETEn创建节点CREATE命令语法Neo4jCQL“CREATE”命令用于创建没有属性的节点。它只是创建一个没有任何数据的节点。CREATE(<node-name>:<label-name>{<Property1-name>:<Property1-Value>..............
  • teamcenter awc 这两个柱状图数据比例差别太大,导致进行中的13条数据显示不出来,点击事
    原因: 解决方法:修改参数: ......
  • .NET Core6.0配置JWT
    环境 ASP.NETCoreWebAPIJWT的一些讲解和与Session的区别俺就不多说了可以去官方文档了解一下直接上代码简单粗暴(以下操作都是在ASP.NETCoreWebAPI进行操作)第一步:引入一个NuGet包  根据自己.NET版本选择对应的版本号 第二步:在appsettings.json配置一些信息"A......
  • 笔记整理--C语言--很酷的C语言技巧 - 博客 - 伯乐在线——转载
    C语言常常让人觉得它所能表达的东西非常有限。它不具有类似第一级函数和模式匹配这样的高级功能。但是C非常简单,并且仍然有一些非常有用的语法技巧和功能,只是没有多少人知道罢了。指定的初始化很多人都知道像这样来静态地初始化数组:intfibs[]={1,1,2,3,5};C99标准实际......
  • 关于条件变量(C语言)
    由于条件变量必须和互斥锁协同使用,所以在介绍条件前会先介绍一下互斥锁(本文目前只介绍C语言,C++的条件变量可能后期会介绍)1、互斥锁从本质上来说,互斥锁是一把锁,保护共享资源免受并发影响的问题,同一时间只能有一个线程可以访问被保护的资源,从而防止竞态而产生不好的结果......
  • 2023-08-16 flutter之执行命令【flutter doctor】报错:Android sdkmanager tool not fo
    步骤如下: 注:请确保你有足够的空间安装并运行as工具。 ......
  • c/c++参数入栈顺序和参数计算顺序
    如果大家细心的话应该知道c/c++语言函数参数入栈顺序为从右至左,那么为什么这样呢?来看看两个知识点:参数的计算顺序与压栈顺序。参数入栈顺序c/c++中规定了函数参数的压栈顺序是从右至左,函数调用协议会影响函数参数的入栈方式、栈内数据的清除方式、编译器函数名的修饰规则等。参......