首页 > 其他分享 >.Net实现SM2解密sm-crypto

.Net实现SM2解密sm-crypto

时间:2022-11-13 20:25:30浏览次数:52  
标签:ecc crypto SM2 Length sm new byte data public

一、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(PrivateKey, 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);

        }

 

标签:ecc,crypto,SM2,Length,sm,new,byte,data,public
From: https://www.cnblogs.com/huguodong/p/16886786.html

相关文章

  • BUUCTF [ACTF新生赛2020]crypto-rsa3
    题目原型:1fromflagimportFLAG2fromCryptodome.Util.numberimport*3importgmpy24importrandom56e=655377p=getPrime(512)8q=int(gmpy......
  • 一、Java中的B/S、MVC、SSM
    一、常见的软件架构体系分为:C/S架构和B/S架构; 二、B/S架构→服务端结构划分→解耦【高内聚、低耦合】:不同的层级负责不同的工作。B/S三层架构:1.表现层(web层......
  • 2006 An AES smart card implementation resistant to power analysis attacks
    一、对DPA攻击的反制措施1掩码定义:所有中间值通过一个随机值(掩码)m隐藏起来,该掩码由密码设备内部生成,通常与中间值进行异或原理:由于掩码是随机的且对攻击者未知,被掩......
  • Applied Cryptography——对称加密(Symmetric Ciphers)
    对称加密(SymmetricCiphers)对称加密(SymmetricCiphers)1.Cryptology,SymmetricCryptography&CorretnessProperty2.Kerchoff'sPrinciple&xor-function3.一......
  • 《Adaptive Mechanism Design: Learning to Promote Cooperation》 2017-arxiv
    背景及问题:外部代理如何在观察学习智能体的基础上分配额外的奖惩促进学习者之间的合作。创新及问题解决:提出一条规则:通过考虑智能体预期的参数更新来自动学习创建正确......
  • 7.整合SSM(前端+后端)
    4.MyBatis层编写1.编写数据库对应的实体类注:这里的MyBatis层应该和Mybatis-config.xml一同编写,属于同一层,这里编者,喜欢配置文件和Java代码分开编写!自行写的时候建议还是......
  • 7.整合SSM(配置文件)
    7.整合SSM1.环境要求:环境:IDEAMySQL5.7.19Tomcat9Maven3.6要求:需要熟练掌握MySQL数据库,Spring,JavaWeb及MyBatis知识,简单的前端知识;2.数据库表创建一个存放......
  • SSM框架整合(十五)
    你未看此花时,则此花与汝心同归于寂,你来看此花时,此花颜色一时明白起来,便知此花不在你的心外。上一章简单介绍了SpringMVC的拦截器(十四),如果没有看过,​​请观看上一章​​......
  • SM系列国密算法
    其中SM1、SM4、SM7、祖冲之密码(ZUC)是对称算法;SM2、SM9是非对称算法;SM3是哈希算法。目前,这些算法已广泛应用于各个领域中,期待有一天会有采用国密算法的区块链应用出现。一......
  • 试试将.NET7编译为WASM并在Docker上运行
    之前有听到说Docker支持Wasmtime了,刚好.NET7也支持WASM,就带大家来了解一下这个东西,顺便试试它怎么样。因为WASM(WebAssembly)一开始是一个给浏览器的技术,比起JS解释执行,W......