百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

.Net实现SM2解密sm-crypto

toyiye 2024-06-21 19:13 14 浏览 0 评论

一、Vue代码

const cipherMode = 0 // 1 - C1C3C2,0 - C1C2C3,默认为1
const publicKey =
    'xxx'

let encryptData = sm2.doEncrypt("加密内容", publicKey, cipherMode);

二、C#实现

1.引用包 :Portable.BouncyCastle

3.编写工具类

    /// <summary>
    /// SM2工具类
    /// </summary>
    public class SM2CryptoUtil
    {

        #region 获取公钥私钥
        /// <summary>
        /// 获取公钥私钥
        /// </summary>
        /// <returns></returns>
        public static SM2Model GetKey()
        {
            SM2 sm2 = SM2.Instance;
            AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.GenerateKeyPair();
            ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters)key.Private;
            ECPublicKeyParameters ecpub = (ECPublicKeyParameters)key.Public;
            BigInteger privateKey = ecpriv.D;
            ECPoint publicKey = ecpub.Q;
            SM2Model sM2Model = new SM2Model();
            sM2Model.PrivateKey = Encoding.UTF8.GetString(Hex.Encode(privateKey.ToByteArray())).ToUpper();
            sM2Model.PublicKey = Encoding.UTF8.GetString(Hex.Encode(publicKey.GetEncoded())).ToUpper();
            return sM2Model;
        }
        #endregion

        #region 加密
        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="publickey">公钥</param>
        /// <param name="sourceData">需要加密的值</param>
        /// <returns>加密结果</returns>
        public static string Encrypt(string publickey, string sourceData)
        {
            var data = Encrypt(Hex.Decode(publickey), Encoding.UTF8.GetBytes(sourceData));
            return data;
        }

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="publicKey">公钥</param>
        /// <param name="data">需要加密的值</param>
        /// <returns></returns>
        public static String Encrypt(byte[] publicKey, byte[] data)
        {
            if (null == publicKey || publicKey.Length == 0)
            {
                return null;
            }
            if (data == null || data.Length == 0)
            {
                return null;
            }

            byte[] source = new byte[data.Length];
            Array.Copy(data, 0, source, 0, data.Length);

            Cipher cipher = new Cipher();
            SM2 sm2 = SM2.Instance;

            ECPoint userKey = sm2.ecc_curve.DecodePoint(publicKey);

            ECPoint c1 = cipher.Init_enc(sm2, userKey);
            cipher.Encrypt(source);

            byte[] c3 = new byte[32];
            cipher.Dofinal(c3);

            String sc1 = Encoding.UTF8.GetString(Hex.Encode(c1.GetEncoded()));
            String sc2 = Encoding.UTF8.GetString(Hex.Encode(source));
            String sc3 = Encoding.UTF8.GetString(Hex.Encode(c3));

            return (sc1 + sc2 + sc3).ToUpper();
        }
        #endregion

        #region 解密

        /// <summary>
        /// 
        /// </summary>
        /// <param name="privateKey"></param>
        /// <param name="encryptedData"></param>
        /// <returns></returns>
        public static string Decrypt(string privateKey, string encryptedData)
        {
            var data = Encoding.UTF8.GetString(Decrypt(Hex.Decode(privateKey), Hex.Decode(encryptedData)));
            return data;
        }
        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="privateKey"></param>
        /// <param name="encryptedData"></param>
        /// <returns></returns>
        public static byte[] Decrypt(byte[] privateKey, byte[] encryptedData)
        {
            if (null == privateKey || privateKey.Length == 0)
            {
                return null;
            }
            if (encryptedData == null || encryptedData.Length == 0)
            {
                return null;
            }

            String data = Encoding.UTF8.GetString(Hex.Encode(encryptedData));

            byte[] c1Bytes = Hex.Decode(Encoding.UTF8.GetBytes(data.Substring(0, 130)));
            int c2Len = encryptedData.Length - 97;
            byte[] c2 = Hex.Decode(Encoding.UTF8.GetBytes(data.Substring(130, 2 * c2Len)));
            byte[] c3 = Hex.Decode(Encoding.UTF8.GetBytes(data.Substring(130 + 2 * c2Len, 64)));

            SM2 sm2 = SM2.Instance;
            BigInteger userD = new BigInteger(1, privateKey);

            //ECPoint c1 = sm2.ecc_curve.DecodePoint(c1Bytes);

            ECPoint c1 = sm2.ecc_curve.DecodePoint(c1Bytes);
            Cipher cipher = new Cipher();
            cipher.Init_dec(userD, c1);
            cipher.Decrypt(c2);
            cipher.Dofinal(c3);

            return c2;
        }
        #endregion

        private class Cipher
        {
            private int ct;
            private ECPoint p2;
            private SM3Digest sm3keybase;
            private SM3Digest sm3c3;
            private byte[] key;
            private byte keyOff;

            public Cipher()
            {
                this.ct = 1;
                this.key = new byte[32];
                this.keyOff = 0;
            }

            public static byte[] byteConvert32Bytes(BigInteger n)
            {
                byte[] tmpd = null;
                if (n == null)
                {
                    return null;
                }

                if (n.ToByteArray().Length == 33)
                {
                    tmpd = new byte[32];
                    Array.Copy(n.ToByteArray(), 1, tmpd, 0, 32);
                }
                else if (n.ToByteArray().Length == 32)
                {
                    tmpd = n.ToByteArray();
                }
                else
                {
                    tmpd = new byte[32];
                    for (int i = 0; i < 32 - n.ToByteArray().Length; i++)
                    {
                        tmpd[i] = 0;
                    }
                    Array.Copy(n.ToByteArray(), 0, tmpd, 32 - n.ToByteArray().Length, n.ToByteArray().Length);
                }
                return tmpd;
            }

            private void Reset()
            {
                this.sm3keybase = new SM3Digest();
                this.sm3c3 = new SM3Digest();

                byte[] p = byteConvert32Bytes(p2.Normalize().XCoord.ToBigInteger());
                this.sm3keybase.BlockUpdate(p, 0, p.Length);
                this.sm3c3.BlockUpdate(p, 0, p.Length);

                p = byteConvert32Bytes(p2.Normalize().YCoord.ToBigInteger());
                this.sm3keybase.BlockUpdate(p, 0, p.Length);
                this.ct = 1;
                NextKey();
            }

            private void NextKey()
            {
                SM3Digest sm3keycur = new SM3Digest(this.sm3keybase);
                sm3keycur.Update((byte)(ct >> 24 & 0xff));
                sm3keycur.Update((byte)(ct >> 16 & 0xff));
                sm3keycur.Update((byte)(ct >> 8 & 0xff));
                sm3keycur.Update((byte)(ct & 0xff));
                sm3keycur.DoFinal(key, 0);
                this.keyOff = 0;
                this.ct++;
            }

            public ECPoint Init_enc(SM2 sm2, ECPoint userKey)
            {
                AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.GenerateKeyPair();
                ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters)key.Private;
                ECPublicKeyParameters ecpub = (ECPublicKeyParameters)key.Public;
                BigInteger k = ecpriv.D;
                ECPoint c1 = ecpub.Q;
                this.p2 = userKey.Multiply(k);
                Reset();
                return c1;
            }

            public void Encrypt(byte[] data)
            {
                this.sm3c3.BlockUpdate(data, 0, data.Length);
                for (int i = 0; i < data.Length; i++)
                {
                    if (keyOff == key.Length)
                    {
                        NextKey();
                    }
                    data[i] ^= key[keyOff++];
                }
            }

            public void Init_dec(BigInteger userD, ECPoint c1)
            {
                this.p2 = c1.Multiply(userD);
                Reset();
            }

            public void Decrypt(byte[] data)
            {
                for (int i = 0; i < data.Length; i++)
                {
                    if (keyOff == key.Length)
                    {
                        NextKey();
                    }
                    data[i] ^= key[keyOff++];
                }

                this.sm3c3.BlockUpdate(data, 0, data.Length);
            }

            public void Dofinal(byte[] c3)
            {
                byte[] p = byteConvert32Bytes(p2.Normalize().YCoord.ToBigInteger());
                this.sm3c3.BlockUpdate(p, 0, p.Length);
                this.sm3c3.DoFinal(c3, 0);
                Reset();
            }
        }
        private class SM2
        {
            public static SM2 Instance
            {
                get
                {
                    return new SM2();
                }

            }
            public static SM2 InstanceTest
            {
                get
                {
                    return new SM2();
                }

            }

            public static readonly string[] sm2_param = {
            "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",// p,0
            "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",// a,1
            "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",// b,2
            "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",// n,3
            "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",// gx,4
            "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0" // gy,5
        };

            public string[] ecc_param = sm2_param;

            public readonly BigInteger ecc_p;
            public readonly BigInteger ecc_a;
            public readonly BigInteger ecc_b;
            public readonly BigInteger ecc_n;
            public readonly BigInteger ecc_gx;
            public readonly BigInteger ecc_gy;

            public readonly ECCurve ecc_curve;
            public readonly ECPoint ecc_point_g;

            public readonly ECDomainParameters ecc_bc_spec;

            public readonly ECKeyPairGenerator ecc_key_pair_generator;

            private SM2()
            {
                ecc_param = sm2_param;

                ECFieldElement ecc_gx_fieldelement;
                ECFieldElement ecc_gy_fieldelement;

                ecc_p = new BigInteger(ecc_param[0], 16);
                ecc_a = new BigInteger(ecc_param[1], 16);
                ecc_b = new BigInteger(ecc_param[2], 16);
                ecc_n = new BigInteger(ecc_param[3], 16);
                ecc_gx = new BigInteger(ecc_param[4], 16);
                ecc_gy = new BigInteger(ecc_param[5], 16);


                ecc_gx_fieldelement = new FpFieldElement(ecc_p, ecc_gx);
                ecc_gy_fieldelement = new FpFieldElement(ecc_p, ecc_gy);

                ecc_curve = new FpCurve(ecc_p, ecc_a, ecc_b);
                ecc_point_g = new FpPoint(ecc_curve, ecc_gx_fieldelement, ecc_gy_fieldelement);

                ecc_bc_spec = new ECDomainParameters(ecc_curve, ecc_point_g, ecc_n);

                ECKeyGenerationParameters ecc_ecgenparam;
                ecc_ecgenparam = new ECKeyGenerationParameters(ecc_bc_spec, new SecureRandom());

                ecc_key_pair_generator = new ECKeyPairGenerator();
                ecc_key_pair_generator.Init(ecc_ecgenparam);
            }

            public virtual byte[] Sm2GetZ(byte[] userId, ECPoint userKey)
            {
                SM3Digest sm3 = new SM3Digest();
                byte[] p;
                // userId length
                int len = userId.Length * 8;
                sm3.Update((byte)(len >> 8 & 0x00ff));
                sm3.Update((byte)(len & 0x00ff));

                // userId
                sm3.BlockUpdate(userId, 0, userId.Length);

                // a,b
                p = ecc_a.ToByteArray();
                sm3.BlockUpdate(p, 0, p.Length);
                p = ecc_b.ToByteArray();
                sm3.BlockUpdate(p, 0, p.Length);
                // gx,gy
                p = ecc_gx.ToByteArray();
                sm3.BlockUpdate(p, 0, p.Length);
                p = ecc_gy.ToByteArray();
                sm3.BlockUpdate(p, 0, p.Length);

                // x,y
                p = userKey.AffineXCoord.ToBigInteger().ToByteArray();
                sm3.BlockUpdate(p, 0, p.Length);
                p = userKey.AffineYCoord.ToBigInteger().ToByteArray();
                sm3.BlockUpdate(p, 0, p.Length);

                // Z
                byte[] md = new byte[sm3.GetDigestSize()];
                sm3.DoFinal(md, 0);

                return md;
            }
        }
        public class SM2Model
        {
            /// <summary>
            /// 公钥
            /// </summary>
            public string PublicKey { get; set; }
            /// <summary>
            /// 私钥
            /// </summary>
            public string PrivateKey { get; set; }
        }
    }

3.调用方法

/// <summary>
        /// 公钥
        /// </summary>
        public static string PublicKey ="xx";

        /// <summary>
        /// 私钥
        /// </summary>
        public static string PrivateKey = "xx";

        /// <summary>
        /// 公钥加密明文
        /// </summary>
        /// <param name="plainText">明文</param>
        /// <returns>密文</returns>
        public static string Encrypt(string plainText)
        {
            return SM2CryptoUtil.Encrypt(PublicKey, plainText);
        }

        /// <summary>
        /// 私钥解密密文
        /// </summary>
        /// <param name="cipherText">密文</param>
        /// <returns>明文</returns>
        public static string Decrypt(string cipherText)
        {
            if (!cipherText.StartsWith("04")) cipherText = "04" + cipherText;//如果不是04开头加上04
            return SM2CryptoUtil.Decrypt(PrivateKey, cipherText);

        }

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码