精华内容
下载资源
问答
  • sm2签名实现
    千次阅读
    2020-09-29 16:50:08
    public String sm2Sign(String text) throws SignatureException {
    		return Sm2Utils.createSM2Signature(text, smSignPrikey);
    	}
    //参数text代表需要签名的明文
    

    使用这个签名算法需要导入crypto-1.0-SNAPSHOT.jar
    使用这个工具类生成公私钥
    Win64OpenSSL-1_1_1g.msi
    如果需要jar包或者工具的或者需要SM2工具类可以私信我。免费提供。

    更多相关内容
  • 1)参数一smType:填写固定字符串,识别功能,分别实现SM2签名、SM4解密、SM4加密。SM2签名入参填写“SM2Sign”、SM4解密入参填写“SM4DecryptECB”、SM4加密入参填写“SM4EncryptECB”. 2)参数二sM2Prikey:SM2...
  • 1)参数一smType:填写固定字符串,识别功能,分别实现SM2签名、SM4解密、SM4加密。SM2签名入参填写“SM2Sign”、SM4解密入参填写“SM4DecryptECB”、SM4加密入参填写“SM4EncryptECB”. 2)参数二sM2Prikey:SM2...
  • 【转】C#sm2签名验签实现

    千次阅读 热门讨论 2022-06-09 18:12:56
    【转】C#sm2签名验签实现
    //调用
    private string Sm2String(string str)
            {
                //sm加密
                SM2Param sM2Param = new SM2Param();
    
                byte[] priKey = Base64.Decode("V8pHqP6TGcQNWhMzEfI0HC0ov66666");
                byte[] pubKey = Convert.FromBase64String("BGqk8Y1gDzo6KYjUcL636thKuGc766666");
                
                ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(new BigInteger(1, priKey), sM2Param.ecc_bc_spec);
                ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(sM2Param.ecc_curve.DecodePoint(pubKey), sM2Param.ecc_bc_spec);
                //签名验签
                byte[] msg = System.Text.Encoding.UTF8.GetBytes(str);
                byte[] userId = System.Text.Encoding.UTF8.GetBytes("1G0H18EPJ07N3F60C8066666");
                byte[] sig = GmUtil.SignSm3WithSm2(msg, userId, privateKeyParameters);
                //string ss = Hex.ToHexString(sig);
    
                return Convert.ToBase64String(sig);
            }
    

    GmUtil_1 工具类

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using Org.BouncyCastle.Asn1.X9;
    using Org.BouncyCastle.Asn1.GM;
    using Org.BouncyCastle.Crypto.Parameters;
    using Org.BouncyCastle.Crypto;
    using Org.BouncyCastle.Security;
    using Org.BouncyCastle.Crypto.Engines;
    using log4net;
    using Org.BouncyCastle.Crypto.Digests;
    using Org.BouncyCastle.Utilities;
    using Org.BouncyCastle.Utilities.Encoders;
    using Org.BouncyCastle.Crypto.Generators;
    using System.IO;
    using Org.BouncyCastle.X509;
    using Org.BouncyCastle.Math;
    using Org.BouncyCastle.Asn1;
    using Org.BouncyCastle.Math.EC;
    using Org.BouncyCastle.Asn1.Ocsp;
    
    namespace YB_PayInterface
    {
        /**
         * need lib:
         * BouncyCastle.Crypto.dll(http://www.bouncycastle.org/csharp/index.html)(这段代码写的时候用的bccrypto-csharp-1.8.8,最低支持版本和最高支持版本自己研究)
         * log4net.dll(http://logging.apache.org/log4net/)(仅为了输出日志用,不用的话可自行改换其他方式输出异常信息)
         *
         * ref:
         * https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02
         * http://gmssl.org/docs/oid.html
         * http://www.jonllen.com/jonllen/work/164.aspx
         *
         * 用BC的注意点:
         * 这个版本的BC对SM3withSM2的结果为asn1格式的r和s,如果需要直接拼接的r||s需要自己转换。下面rsAsn1ToPlainByteArray、rsPlainByteArrayToAsn1就在干这事。
         * 这个版本的BC对SM2的结果为C1||C2||C3,据说为旧标准,新标准为C1||C3||C2,用新标准的需要自己转换。下面(被注释掉的)changeC1C2C3ToC1C3C2、changeC1C3C2ToC1C2C3就在干这事。java版的高版本有加上C1C3C2,csharp版没准以后也会加,但目前还没有,java版的目前可以初始化时“ SM2Engine sm2Engine = new SM2Engine(SM2Engine.Mode.C1C3C2);”。
         * 
         * 按要求国密算法仅允许使用加密机,本demo国密算法仅供学习使用,请不要用于生产用途。
         */
        public class GmUtil_1
        {
    
            private static readonly ILog log = LogManager.GetLogger(typeof(GmUtil));
    
            private static X9ECParameters x9ECParameters = GMNamedCurves.GetByName("sm2p256v1");
            private static ECDomainParameters ecDomainParameters = new ECDomainParameters(x9ECParameters.Curve, x9ECParameters.G, x9ECParameters.N);
            //private static DerApplicationSpecific ecParameterSpec = new DerApplicationSpecific(x9ECParameters.Curve, x9ECParameters.G, x9ECParameters.N);
    
    
            /**
             *
             * @param msg
             * @param userId
             * @param privateKey
             * @return r||s,直接拼接byte数组的rs
             */
            public static byte[] SignSm3WithSm2(byte[] msg, byte[] userId, AsymmetricKeyParameter privateKey)
            {
                return RsAsn1ToPlainByteArray(SignSm3WithSm2Asn1Rs(msg, userId, privateKey));
            }
    
            /**
              * @param msg
              * @param userId
              * @param privateKey
              * @return rs in <b>asn1 format</b>
              */
            public static byte[] SignSm3WithSm2Asn1Rs(byte[] msg, byte[] userId, AsymmetricKeyParameter privateKey)
            {
                try
                {
                    ISigner signer = SignerUtilities.GetSigner("SM3withSM2");
                    signer.Init(true, new ParametersWithID(privateKey, userId));
                    signer.BlockUpdate(msg, 0, msg.Length);
                    byte[] sig = signer.GenerateSignature();
                    return sig;
                }
                catch (Exception e)
                {
                    log.Error("SignSm3WithSm2Asn1Rs error: " + e.Message, e);
                    return null;
                }
            }
    
            public static byte[] signSm3WithSm2(byte[] msg, byte[] userId, byte[] privateKeyBytes)
            {
                ECPrivateKeyParameters bcecPrivateKey = GetPrivatekeyFromD(new BigInteger(privateKeyBytes));
                return signSm3WithSm2(msg, userId, bcecPrivateKey);
            }
    
            public static byte[] signSm3WithSm2(byte[] msg, byte[] userId, ECPrivateKeyParameters privateKey)
            {
                return RsAsn1ToPlainByteArray(SignSm3WithSm2Asn1Rs(msg, userId, privateKey));
            }
    
            /**
            *
            * @param msg
            * @param userId
            * @param rs r||s,直接拼接byte数组的rs
            * @param publicKey
            * @return
            */
            public static bool VerifySm3WithSm2(byte[] msg, byte[] userId, byte[] rs, AsymmetricKeyParameter publicKey)
            {
                if (rs == null || msg == null || userId == null) return false;
                if (rs.Length != RS_LEN * 2) return false;
                return VerifySm3WithSm2Asn1Rs(msg, userId, RsPlainByteArrayToAsn1(rs), publicKey);
            }
    
            /**
             *
             * @param msg
             * @param userId
             * @param rs in <b>asn1 format</b>
             * @param publicKey
             * @return
             */
            public static bool VerifySm3WithSm2Asn1Rs(byte[] msg, byte[] userId, byte[] sign, AsymmetricKeyParameter publicKey)
            {
                try
                {
                    ISigner signer = SignerUtilities.GetSigner("SM3withSM2");
                    signer.Init(false, new ParametersWithID(publicKey, userId));
                    signer.BlockUpdate(msg, 0, msg.Length);
                    return signer.VerifySignature(sign);
                }
                catch (Exception e)
                {
                    log.Error("VerifySm3WithSm2Asn1Rs error: " + e.Message, e);
                    return false;
                }
            }
    
            /**
             * bc加解密使用旧标c1||c2||c3,此方法在加密后调用,将结果转化为c1||c3||c2
             * @param c1c2c3
             * @return
             */
            private static byte[] ChangeC1C2C3ToC1C3C2(byte[] c1c2c3)
            {
                int c1Len = (x9ECParameters.Curve.FieldSize + 7) / 8 * 2 + 1; //sm2p256v1的这个固定65。可看GMNamedCurves、ECCurve代码。
                const int c3Len = 32; //new SM3Digest().getDigestSize();
                byte[] result = new byte[c1c2c3.Length];
                Buffer.BlockCopy(c1c2c3, 0, result, 0, c1Len); //c1
                Buffer.BlockCopy(c1c2c3, c1c2c3.Length - c3Len, result, c1Len, c3Len); //c3
                Buffer.BlockCopy(c1c2c3, c1Len, result, c1Len + c3Len, c1c2c3.Length - c1Len - c3Len); //c2
                return result;
            }
    
            /**
             * bc加解密使用旧标c1||c3||c2,此方法在解密前调用,将密文转化为c1||c2||c3再去解密
             * @param c1c3c2
             * @return
             */
            private static byte[] ChangeC1C3C2ToC1C2C3(byte[] c1c3c2)
            {
                int c1Len = (x9ECParameters.Curve.FieldSize + 7) / 8 * 2 + 1; //sm2p256v1的这个固定65。可看GMNamedCurves、ECCurve代码。
                const int c3Len = 32; //new SM3Digest().GetDigestSize();
                byte[] result = new byte[c1c3c2.Length];
                Buffer.BlockCopy(c1c3c2, 0, result, 0, c1Len); //c1: 0->65
                Buffer.BlockCopy(c1c3c2, c1Len + c3Len, result, c1Len, c1c3c2.Length - c1Len - c3Len); //c2
                Buffer.BlockCopy(c1c3c2, c1Len, result, c1c3c2.Length - c3Len, c3Len); //c3
                return result;
            }
    
            /**
             * c1||c3||c2
             * @param data
             * @param key
             * @return
             */
            public static byte[] Sm2Decrypt(byte[] data, AsymmetricKeyParameter key)
            {
                return Sm2DecryptOld(ChangeC1C3C2ToC1C2C3(data), key);
            }
    
            /**
             * c1||c3||c2
             * @param data
             * @param key
             * @return
             */
    
            public static byte[] Sm2Encrypt(byte[] data, AsymmetricKeyParameter key)
            {
                return ChangeC1C2C3ToC1C3C2(Sm2EncryptOld(data, key));
            }
    
            /**
             * c1||c2||c3
             * @param data
             * @param key
             * @return
             */
            public static byte[] Sm2EncryptOld(byte[] data, AsymmetricKeyParameter pubkey)
            {
                try
                {
                    SM2Engine sm2Engine = new SM2Engine();
                    sm2Engine.Init(true, new ParametersWithRandom(pubkey, new SecureRandom()));
                    return sm2Engine.ProcessBlock(data, 0, data.Length);
                }
                catch (Exception e)
                {
                    log.Error("Sm2EncryptOld error: " + e.Message, e);
                    return null;
                }
            }
    
            /**
             * c1||c2||c3
             * @param data
             * @param key
             * @return
             */
            public static byte[] Sm2DecryptOld(byte[] data, AsymmetricKeyParameter key)
            {
                try
                {
                    SM2Engine sm2Engine = new SM2Engine();
                    sm2Engine.Init(false, key);
                    return sm2Engine.ProcessBlock(data, 0, data.Length);
                }
                catch (Exception e)
                {
                    log.Error("Sm2DecryptOld error: " + e.Message, e);
                    return null;
                }
            }
    
            /**
             * @param bytes
             * @return
             */
            public static byte[] Sm3(byte[] bytes)
            {
                try
                {
                    SM3Digest digest = new SM3Digest();
                    digest.BlockUpdate(bytes, 0, bytes.Length);
                    byte[] result = DigestUtilities.DoFinal(digest);
                    return result;
                }
                catch (Exception e)
                {
                    log.Error("Sm3 error: " + e.Message, e);
                    return null;
                }
            }
    
            private const int RS_LEN = 32;
    
            private static byte[] BigIntToFixexLengthBytes(BigInteger rOrS)
            {
                // for sm2p256v1, n is 00fffffffeffffffffffffffffffffffff7203df6b21c6052b53bbf40939d54123,
                // r and s are the result of mod n, so they should be less than n and have length<=32
                byte[] rs = rOrS.ToByteArray();
                if (rs.Length == RS_LEN) return rs;
                else if (rs.Length == RS_LEN + 1 && rs[0] == 0) return Arrays.CopyOfRange(rs, 1, RS_LEN + 1);
                else if (rs.Length < RS_LEN)
                {
                    byte[] result = new byte[RS_LEN];
                    Arrays.Fill(result, (byte)0);
                    Buffer.BlockCopy(rs, 0, result, RS_LEN - rs.Length, rs.Length);
                    return result;
                }
                else
                {
                    throw new ArgumentException("err rs: " + Hex.ToHexString(rs));
                }
            }
    
            /**
             * BC的SM3withSM2签名得到的结果的rs是asn1格式的,这个方法转化成直接拼接r||s
             * @param rsDer rs in asn1 format
             * @return sign result in plain byte array
             */
            private static byte[] RsAsn1ToPlainByteArray(byte[] rsDer)
            {
                Asn1Sequence seq = Asn1Sequence.GetInstance(rsDer);
                byte[] r = BigIntToFixexLengthBytes(DerInteger.GetInstance(seq[0]).Value);
                byte[] s = BigIntToFixexLengthBytes(DerInteger.GetInstance(seq[1]).Value);
                byte[] result = new byte[RS_LEN * 2];
                Buffer.BlockCopy(r, 0, result, 0, r.Length);
                Buffer.BlockCopy(s, 0, result, RS_LEN, s.Length);
                return result;
            }
    
            /**
             * BC的SM3withSM2验签需要的rs是asn1格式的,这个方法将直接拼接r||s的字节数组转化成asn1格式
             * @param sign in plain byte array
             * @return rs result in asn1 format
             */
            private static byte[] RsPlainByteArrayToAsn1(byte[] sign)
            {
                if (sign.Length != RS_LEN * 2) throw new ArgumentException("err rs. ");
                BigInteger r = new BigInteger(1, Arrays.CopyOfRange(sign, 0, RS_LEN));
                BigInteger s = new BigInteger(1, Arrays.CopyOfRange(sign, RS_LEN, RS_LEN * 2));
                Asn1EncodableVector v = new Asn1EncodableVector();
                v.Add(new DerInteger(r));
                v.Add(new DerInteger(s));
                try
                {
                    return new DerSequence(v).GetEncoded("DER");
                }
                catch (IOException e)
                {
                    log.Error("RsPlainByteArrayToAsn1 error: " + e.Message, e);
                    return null;
                }
            }
    
            public static AsymmetricCipherKeyPair GenerateKeyPair()
            {
                try
                {
                    ECKeyPairGenerator kpGen = new ECKeyPairGenerator();
                    kpGen.Init(new ECKeyGenerationParameters(ecDomainParameters, new SecureRandom()));
                    return kpGen.GenerateKeyPair();
                }
                catch (Exception e)
                {
                    log.Error("generateKeyPair error: " + e.Message, e);
                    return null;
                }
            }
    
            public static ECPrivateKeyParameters GetPrivatekeyFromD(BigInteger d)
            {
                return new ECPrivateKeyParameters(d, ecDomainParameters);
            }
    
            public static ECPublicKeyParameters GetPublickeyFromXY(BigInteger x, BigInteger y)
            {
                return new ECPublicKeyParameters(x9ECParameters.Curve.CreatePoint(x, y), ecDomainParameters);
            }
    
            public static AsymmetricKeyParameter GetPublickeyFromX509File(FileInfo file)
            {
    
                FileStream fileStream = null;
                try
                {
                    //file.DirectoryName + "\\" + file.Name
                    fileStream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read);
                    X509Certificate certificate = new X509CertificateParser().ReadCertificate(fileStream);
                    return certificate.GetPublicKey();
                }
                catch (Exception e)
                {
                    log.Error(file.Name + "读取失败,异常:" + e);
                }
                finally
                {
                    if (fileStream != null)
                        fileStream.Close();
                }
                return null;
            }
    
            public class Sm2Cert
            {
                public AsymmetricKeyParameter privateKey;
                public AsymmetricKeyParameter publicKey;
                public String certId;
            }
    
            private static byte[] ToByteArray(int i)
            {
                byte[] byteArray = new byte[4];
                byteArray[0] = (byte)(i >> 24);
                byteArray[1] = (byte)((i & 0xFFFFFF) >> 16);
                byteArray[2] = (byte)((i & 0xFFFF) >> 8);
                byteArray[3] = (byte)(i & 0xFF);
                return byteArray;
            }
    
            /**
             * 字节数组拼接
             *
             * @param params
             * @return
             */
            private static byte[] Join(params byte[][] byteArrays)
            {
                List<byte> byteSource = new List<byte>();
                for (int i = 0; i < byteArrays.Length; i++)
                {
                    byteSource.AddRange(byteArrays[i]);
                }
                byte[] data = byteSource.ToArray();
                return data;
            }
    
            /**
             * 密钥派生函数
             *
             * @param Z
             * @param klen
             *            生成klen字节数长度的密钥
             * @return
             */
            private static byte[] KDF(byte[] Z, int klen)
            {
                int ct = 1;
                int end = (int)Math.Ceiling(klen * 1.0 / 32);
                List<byte> byteSource = new List<byte>();
                try
                {
                    for (int i = 1; i < end; i++)
                    {
                        byteSource.AddRange(GmUtil.Sm3(Join(Z, ToByteArray(ct))));
                        ct++;
                    }
                    byte[] last = GmUtil.Sm3(Join(Z, ToByteArray(ct)));
                    if (klen % 32 == 0)
                    {
                        byteSource.AddRange(last);
                    }
                    else
                        byteSource.AddRange(Arrays.CopyOfRange(last, 0, klen % 32));
                    return byteSource.ToArray();
                }
                catch (Exception e)
                {
                    log.Error("KDF error: " + e.Message, e);
                }
                return null;
            }
    
            public static byte[] Sm4DecryptCBC(byte[] keyBytes, byte[] cipher, byte[] iv, String algo)
            {
                if (keyBytes.Length != 16) throw new ArgumentException("err key length");
                if (cipher.Length % 16 != 0) throw new ArgumentException("err data length");
    
                try
                {
                    KeyParameter key = ParameterUtilities.CreateKeyParameter("SM4", keyBytes);
                    IBufferedCipher c = CipherUtilities.GetCipher(algo);
                    if (iv == null) iv = ZeroIv(algo);
                    c.Init(false, new ParametersWithIV(key, iv));
                    return c.DoFinal(cipher);
                }
                catch (Exception e)
                {
                    log.Error("Sm4DecryptCBC error: " + e.Message, e);
                    return null;
                }
            }
    
    
            public static byte[] Sm4EncryptCBC(byte[] keyBytes, byte[] plain, byte[] iv, String algo)
            {
                if (keyBytes.Length != 16) throw new ArgumentException("err key length");
                if (plain.Length % 16 != 0) throw new ArgumentException("err data length");
    
                try
                {
                    KeyParameter key = ParameterUtilities.CreateKeyParameter("SM4", keyBytes);
                    IBufferedCipher c = CipherUtilities.GetCipher(algo);
                    if (iv == null) iv = ZeroIv(algo);
                    c.Init(true, new ParametersWithIV(key, iv));
                    return c.DoFinal(plain);
                }
                catch (Exception e)
                {
                    log.Error("Sm4EncryptCBC error: " + e.Message, e);
                    return null;
                }
            }
    
    
            public static byte[] Sm4EncryptECB(byte[] keyBytes, byte[] plain, string algo)
            {
                if (keyBytes.Length != 16) throw new ArgumentException("err key length");
                if (plain.Length % 16 != 0) throw new ArgumentException("err data length");
    
                try
                {
                    KeyParameter key = ParameterUtilities.CreateKeyParameter("SM4", keyBytes);
                    IBufferedCipher c = CipherUtilities.GetCipher(algo);
                    c.Init(true, key);
                    return c.DoFinal(plain);
                }
                catch (Exception e)
                {
                    log.Error("Sm4EncryptECB error: " + e.Message, e);
                    return null;
                }
            }
    
            public static byte[] Sm4DecryptECB(byte[] keyBytes, byte[] cipher, string algo)
            {
                if (keyBytes.Length != 16) throw new ArgumentException("err key length");
                if (cipher.Length % 16 != 0) throw new ArgumentException("err data length");
    
                try
                {
                    KeyParameter key = ParameterUtilities.CreateKeyParameter("SM4", keyBytes);
                    IBufferedCipher c = CipherUtilities.GetCipher(algo);
                    c.Init(false, key);
                    return c.DoFinal(cipher);
                }
                catch (Exception e)
                {
                    log.Error("Sm4DecryptECB error: " + e.Message, e);
                    return null;
                }
            }
    
            public const String SM4_ECB_NOPADDING = "SM4/ECB/NoPadding";
            public const String SM4_CBC_NOPADDING = "SM4/CBC/NoPadding";
            public const String SM4_CBC_PKCS7PADDING = "SM4/CBC/PKCS7Padding";
    
            /**
             * cfca官网CSP沙箱导出的sm2文件
             * @param pem 二进制原文
             * @param pwd 密码
             * @return
             */
            public static Sm2Cert readSm2File(byte[] pem, String pwd)
            {
    
                Sm2Cert sm2Cert = new Sm2Cert();
                try
                {
                    Asn1Sequence asn1Sequence = (Asn1Sequence)Asn1Object.FromByteArray(pem);
                    //	    	ASN1Integer asn1Integer = (ASN1Integer) asn1Sequence.getObjectAt(0); //version=1
                    Asn1Sequence priSeq = (Asn1Sequence)asn1Sequence[1];//private key
                    Asn1Sequence pubSeq = (Asn1Sequence)asn1Sequence[2];//public key and x509 cert
    
                    //	    	ASN1ObjectIdentifier sm2DataOid = (ASN1ObjectIdentifier) priSeq.getObjectAt(0);
                    //	    	ASN1ObjectIdentifier sm4AlgOid = (ASN1ObjectIdentifier) priSeq.getObjectAt(1);
                    Asn1OctetString priKeyAsn1 = (Asn1OctetString)priSeq[2];
                    byte[] key = KDF(System.Text.Encoding.UTF8.GetBytes(pwd), 32);
                    byte[] priKeyD = Sm4DecryptCBC(Arrays.CopyOfRange(key, 16, 32),
                            priKeyAsn1.GetOctets(),
                            Arrays.CopyOfRange(key, 0, 16), SM4_CBC_PKCS7PADDING);
                    sm2Cert.privateKey = GetPrivatekeyFromD(new BigInteger(1, priKeyD));
                    //	    	log.Info(Hex.toHexString(priKeyD));
    
                    //	    	ASN1ObjectIdentifier sm2DataOidPub = (ASN1ObjectIdentifier) pubSeq.getObjectAt(0);
                    Asn1OctetString pubKeyX509 = (Asn1OctetString)pubSeq[1];
                    X509Certificate x509 = (X509Certificate)new X509CertificateParser().ReadCertificate(pubKeyX509.GetOctets());
                    sm2Cert.publicKey = x509.GetPublicKey();
                    sm2Cert.certId = x509.SerialNumber.ToString(10); //这里转10进账,有啥其他进制要求的自己改改
                    return sm2Cert;
                }
                catch (Exception e)
                {
                    log.Error("readSm2File error: " + e.Message, e);
                    return null;
                }
            }
    
            /**
             *
             * @param cert
             * @return
             */
            public static Sm2Cert ReadSm2X509Cert(byte[] cert)
            {
                Sm2Cert sm2Cert = new Sm2Cert();
                try
                {
    
                    X509Certificate x509 = new X509CertificateParser().ReadCertificate(cert);
                    sm2Cert.publicKey = x509.GetPublicKey();
                    sm2Cert.certId = x509.SerialNumber.ToString(10); //这里转10进账,有啥其他进制要求的自己改改
                    return sm2Cert;
                }
                catch (Exception e)
                {
                    log.Error("ReadSm2X509Cert error: " + e.Message, e);
                    return null;
                }
            }
    
            public static byte[] ZeroIv(String algo)
            {
    
                try
                {
                    IBufferedCipher cipher = CipherUtilities.GetCipher(algo);
                    int blockSize = cipher.GetBlockSize();
                    byte[] iv = new byte[blockSize];
                    Arrays.Fill(iv, (byte)0);
                    return iv;
                }
                catch (Exception e)
                {
                    log.Error("ZeroIv error: " + e.Message, e);
                    return null;
                }
            }
    
            public static void Main1(string[] s)
            {
    
                // 随便看看
                //log.Info("GMNamedCurves: ");
                foreach (string e in GMNamedCurves.Names)
                {
                    //log.Info(e);
                }
                //log.Info("sm2p256v1 n:" + x9ECParameters.N);
                //log.Info("sm2p256v1 nHex:" + Hex.ToHexString(x9ECParameters.N.ToByteArray()));
    
                SM2Param sM2Param = new SM2Param();
    
                //Key
                byte[] priKey = Convert.FromBase64String("DENOZDuuon+lHJCNzLyMfwJT8ZSdCcyPeW6JnWWkObo=");
                byte[] pubKey = Convert.FromBase64String("BGUh0gYeUj9WMa15L+QC0P62gJtX6JCrdIAIz96c5dGN6FbtxU7frc2qnL9IhogoHQgO8pt7A3ICSxmgJqiLERc=");
    
                ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(new BigInteger(1, priKey), sM2Param.ecc_bc_spec);
                ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(sM2Param.ecc_curve.DecodePoint(pubKey), sM2Param.ecc_bc_spec);
    
    
                // 生成公私钥对 ---------------------
                //AsymmetricCipherKeyPair kp = GmUtil.GenerateKeyPair();
                //ECPrivateKeyParameters eCPrivate = new ECPrivateKeyParameters()
                //Console.WriteLine("private key d: " + ((ECPrivateKeyParameters)kp.Private).D);
                //Console.WriteLine("public key q:" + ((ECPublicKeyParameters)kp.Public).Q); //{x, y, zs...}
    
                //签名验签
                byte[] msg = System.Text.Encoding.UTF8.GetBytes("message digest");
                byte[] userId = System.Text.Encoding.UTF8.GetBytes("AA00EDC7ACB9F2CB");
                byte[] sig = GmUtil.SignSm3WithSm2(msg, userId, privateKeyParameters);//kp.Private);
                string ss = Hex.ToHexString(sig);
                string result = Convert.ToBase64String(sig);
                bool b = GmUtil.VerifySm3WithSm2(msg, userId, sig, publicKeyParameters);// kp.Public);
    
                Console.ReadKey();
            }
    
            /*
            public static void Main(string[] s)
            {
                //签名验签
                string input = "{         \"signIn\":{             \"opter_no\":\"9999\",             \"mac\":\"70 - B5 - E8 - 48 - 78 - 48\",             \"ip\":\"192.168.2.101\"         }     }";
                byte[] msg = System.Text.Encoding.UTF8.GetBytes(input);
                byte[] userId = System.Text.Encoding.UTF8.GetBytes("AA00EDC7ACB9F2CB");
                byte[] privateKeyBytes = Convert.FromBase64String("DENOZDuuon+lHJCNzLyMfwJT8ZSdCcyPeW6JnWWkObo=");
                byte[] sig = signSm3WithSm2(msg, userId, privateKeyBytes);
                string result = Convert.ToBase64String(sig);
                Console.WriteLine("testSignSm3WithSm2: " + Hex.ToHexString(sig));
                Console.ReadKey();
                //Console.WriteLine("testVerifySm3WithSm2: " + VerifySm3WithSm2(msg, userId, sig, kp.Public));
            }
            */
            //public static void Main(string[] s)
            //{
            //    log.Info("GMNamedCurves: ");
            //    foreach (string e in GMNamedCurves.Names)
            //    {
            //        log.Info(e);
            //    }
            //    log.Info("sm2p256v1 n:" + x9ECParameters.N);
            //    log.Info("sm2p256v1 nHex:" + Hex.ToHexString(x9ECParameters.N.ToByteArray()));
    
            //    // 生成公私钥对 ---------------------
            //    AsymmetricCipherKeyPair kp = GmUtil.GenerateKeyPair();
            //    log.Info("private key d: " + ((ECPrivateKeyParameters)kp.Private).D);
            //    log.Info("public key q:" + ((ECPublicKeyParameters)kp.Public).Q); //{x, y, zs...}
    
            //    //签名验签
            //    byte[] msg = System.Text.Encoding.UTF8.GetBytes("message digest");
            //    byte[] userId = System.Text.Encoding.UTF8.GetBytes("userId");
            //    byte[] sig = SignSm3WithSm2(msg, userId, kp.Private);
            //    log.Info("testSignSm3WithSm2: " + Hex.ToHexString(sig));
            //    log.Info("testVerifySm3WithSm2: " + VerifySm3WithSm2(msg, userId, sig, kp.Public));
    
            //    // 由d生成私钥 ---------------------
            //    BigInteger d = new BigInteger("097b5230ef27c7df0fa768289d13ad4e8a96266f0fcb8de40d5942af4293a54a", 16);
            //    ECPrivateKeyParameters bcecPrivateKey = GetPrivatekeyFromD(d);
            //    log.Info("testGetFromD: " + bcecPrivateKey.D.ToString(16));
    
            //    //公钥X坐标PublicKeyXHex: 59cf9940ea0809a97b1cbffbb3e9d96d0fe842c1335418280bfc51dd4e08a5d4
            //    //公钥Y坐标PublicKeyYHex: 9a7f77c578644050e09a9adc4245d1e6eba97554bc8ffd4fe15a78f37f891ff8
            //    AsymmetricKeyParameter publicKey = GetPublickeyFromX509File(new FileInfo("d:/certs/69629141652.cer"));
            //    log.Info(publicKey);
            //    AsymmetricKeyParameter publicKey1 = GetPublickeyFromXY(new BigInteger("59cf9940ea0809a97b1cbffbb3e9d96d0fe842c1335418280bfc51dd4e08a5d4", 16), new BigInteger("9a7f77c578644050e09a9adc4245d1e6eba97554bc8ffd4fe15a78f37f891ff8", 16));
            //    log.Info("testReadFromX509File: " + ((ECPublicKeyParameters)publicKey).Q);
            //    log.Info("testGetFromXY: " + ((ECPublicKeyParameters)publicKey1).Q);
            //    log.Info("testPubKey: " + publicKey.Equals(publicKey1));
            //    log.Info("testPubKey: " + ((ECPublicKeyParameters)publicKey).Q.Equals(((ECPublicKeyParameters)publicKey1).Q));
    
            //    // sm2 encrypt and decrypt test ---------------------
            //    AsymmetricCipherKeyPair kp2 = GenerateKeyPair();
            //    AsymmetricKeyParameter publicKey2 = kp2.Public;
            //    AsymmetricKeyParameter privateKey2 = kp2.Private;
            //    byte[] bs = Sm2Encrypt(System.Text.Encoding.UTF8.GetBytes("s"), publicKey2);
            //    log.Info("testSm2Enc dec: " + Hex.ToHexString(bs));
            //    bs = Sm2Decrypt(bs, privateKey2);
            //    log.Info("testSm2Enc dec: " + System.Text.Encoding.UTF8.GetString(bs));
    
            //    // sm4 encrypt and decrypt test ---------------------
            //    //0123456789abcdeffedcba9876543210 + 0123456789abcdeffedcba9876543210 -> 681edf34d206965e86b3e94f536e4246
            //    byte[] plain = Hex.Decode("0123456789abcdeffedcba98765432100123456789abcdeffedcba98765432100123456789abcdeffedcba9876543210");
            //    byte[] key = Hex.Decode("0123456789abcdeffedcba9876543210");
            //    byte[] cipher = Hex.Decode("595298c7c6fd271f0402f804c33d3f66");
            //    bs = Sm4EncryptECB(key, plain, GmUtil.SM4_ECB_NOPADDING);
            //    log.Info("testSm4EncEcb: " + Hex.ToHexString(bs)); ;
            //    bs = Sm4DecryptECB(key, bs, GmUtil.SM4_ECB_NOPADDING);
            //    log.Info("testSm4DecEcb: " + Hex.ToHexString(bs));
    
            //    //读.sm2文件
            //    String sm2 = "MIIDHQIBATBHBgoqgRzPVQYBBAIBBgcqgRzPVQFoBDDW5/I9kZhObxXE9Vh1CzHdZhIhxn+3byBU\nUrzmGRKbDRMgI3hJKdvpqWkM5G4LNcIwggLNBgoqgRzPVQYBBAIBBIICvTCCArkwggJdoAMCAQIC\nBRA2QSlgMAwGCCqBHM9VAYN1BQAwXDELMAkGA1UEBhMCQ04xMDAuBgNVBAoMJ0NoaW5hIEZpbmFu\nY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEbMBkGA1UEAwwSQ0ZDQSBURVNUIFNNMiBPQ0Ex\nMB4XDTE4MTEyNjEwMTQxNVoXDTIwMTEyNjEwMTQxNVowcjELMAkGA1UEBhMCY24xEjAQBgNVBAoM\nCUNGQ0EgT0NBMTEOMAwGA1UECwwFQ1VQUkExFDASBgNVBAsMC0VudGVycHJpc2VzMSkwJwYDVQQD\nDCAwNDFAWnRlc3RAMDAwMTAwMDA6U0lHTkAwMDAwMDAwMTBZMBMGByqGSM49AgEGCCqBHM9VAYIt\nA0IABDRNKhvnjaMUShsM4MJ330WhyOwpZEHoAGfqxFGX+rcL9x069dyrmiF3+2ezwSNh1/6YqfFZ\nX9koM9zE5RG4USmjgfMwgfAwHwYDVR0jBBgwFoAUa/4Y2o9COqa4bbMuiIM6NKLBMOEwSAYDVR0g\nBEEwPzA9BghggRyG7yoBATAxMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmNmY2EuY29tLmNuL3Vz\nL3VzLTE0Lmh0bTA4BgNVHR8EMTAvMC2gK6AphidodHRwOi8vdWNybC5jZmNhLmNvbS5jbi9TTTIv\nY3JsNDI4NS5jcmwwCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBREhx9VlDdMIdIbhAxKnGhPx8FcHDAd\nBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwDAYIKoEcz1UBg3UFAANIADBFAiEAgWvQi3h6\niW4jgF4huuXfhWInJmTTYr2EIAdG8V4M8fYCIBixygdmfPL9szcK2pzCYmIb6CBzo5SMv50Odycc\nVfY6";
            //    bs = Convert.FromBase64String(sm2);
            //    String pwd = "cfca1234";
            //    GmUtil.Sm2Cert sm2Cert = GmUtil.readSm2File(bs, pwd);
            //    log.Info("testReadSm2File, pubkey: " + ((ECPublicKeyParameters)sm2Cert.publicKey).Q.ToString());
            //    log.Info("testReadSm2File, prikey: " + Hex.ToHexString(((ECPrivateKeyParameters)sm2Cert.privateKey).D.ToByteArray()));
            //    log.Info("testReadSm2File, certId: " + sm2Cert.certId);
    
            //    bs = Sm2Encrypt(System.Text.Encoding.UTF8.GetBytes("s"), ((ECPublicKeyParameters)sm2Cert.publicKey));
            //    log.Info("testSm2Enc dec: " + Hex.ToHexString(bs));
            //    bs = Sm2Decrypt(bs, ((ECPrivateKeyParameters)sm2Cert.privateKey));
            //    log.Info("testSm2Enc dec: " + System.Text.Encoding.UTF8.GetString(bs));
    
            //    msg = System.Text.Encoding.UTF8.GetBytes("message digest");
            //    userId = System.Text.Encoding.UTF8.GetBytes("userId");
            //    sig = SignSm3WithSm2(msg, userId, ((ECPrivateKeyParameters)sm2Cert.privateKey));
            //    log.Info("testSignSm3WithSm2: " + Hex.ToHexString(sig));
            //    log.Info("testVerifySm3WithSm2: " + VerifySm3WithSm2(msg, userId, sig, ((ECPublicKeyParameters)sm2Cert.publicKey)));
            //}
        }
    
        public 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);
            }
        }
    }
    
    
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using Org.BouncyCastle.Asn1.X9;
    using Org.BouncyCastle.Asn1.GM;
    using Org.BouncyCastle.Crypto.Parameters;
    using Org.BouncyCastle.Crypto;
    using Org.BouncyCastle.Security;
    using Org.BouncyCastle.Crypto.Engines;
    using log4net;
    using Org.BouncyCastle.Crypto.Digests;
    using Org.BouncyCastle.Utilities;
    using Org.BouncyCastle.Utilities.Encoders;
    using Org.BouncyCastle.Crypto.Generators;
    using System.IO;
    using Org.BouncyCastle.X509;
    using Org.BouncyCastle.Math;
    using Org.BouncyCastle.Asn1;
    
    namespace YB_PayInterface
    {
        /**
         * need lib:
         * BouncyCastle.Crypto.dll(http://www.bouncycastle.org/csharp/index.html)(这段代码写的时候用的bccrypto-csharp-1.8.8,最低支持版本和最高支持版本自己研究)
         * log4net.dll(http://logging.apache.org/log4net/)(仅为了输出日志用,不用的话可自行改换其他方式输出异常信息)
         *
         * ref:
         * https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02
         * http://gmssl.org/docs/oid.html
         * http://www.jonllen.com/jonllen/work/164.aspx
         *
         * 用BC的注意点:
         * 这个版本的BC对SM3withSM2的结果为asn1格式的r和s,如果需要直接拼接的r||s需要自己转换。下面rsAsn1ToPlainByteArray、rsPlainByteArrayToAsn1就在干这事。
         * 这个版本的BC对SM2的结果为C1||C2||C3,据说为旧标准,新标准为C1||C3||C2,用新标准的需要自己转换。下面(被注释掉的)changeC1C2C3ToC1C3C2、changeC1C3C2ToC1C2C3就在干这事。java版的高版本有加上C1C3C2,csharp版没准以后也会加,但目前还没有,java版的目前可以初始化时“ SM2Engine sm2Engine = new SM2Engine(SM2Engine.Mode.C1C3C2);”。
         * 
         * 按要求国密算法仅允许使用加密机,本demo国密算法仅供学习使用,请不要用于生产用途。
         */
        public class GmUtil
        {
    
            private static readonly ILog log = LogManager.GetLogger(typeof(GmUtil));
    
            private static X9ECParameters x9ECParameters = GMNamedCurves.GetByName("sm2p256v1");
            private static ECDomainParameters ecDomainParameters = new ECDomainParameters(x9ECParameters.Curve, x9ECParameters.G, x9ECParameters.N);
    
            /**
             *
             * @param msg
             * @param userId
             * @param privateKey
             * @return r||s,直接拼接byte数组的rs
             */
            public static byte[] SignSm3WithSm2(byte[] msg, byte[] userId, AsymmetricKeyParameter privateKey)
            {
                return RsAsn1ToPlainByteArray(SignSm3WithSm2Asn1Rs(msg, userId, privateKey));
            }
    
            /**
              * @param msg
              * @param userId
              * @param privateKey
              * @return rs in <b>asn1 format</b>
              */
            public static byte[] SignSm3WithSm2Asn1Rs(byte[] msg, byte[] userId, AsymmetricKeyParameter privateKey)
            {
                try
                {
                    SM2Param sM2Param = new SM2Param();
                    
                    ISigner signer = SignerUtilities.GetSigner("SM3withSM2");
    
                    ICipherParameters cp = new ParametersWithRandom(privateKey);
    
                    //signer.Init(true, new ParametersWithID(privateKey, userId));
                    signer.Init(true, cp);
    
                    signer.BlockUpdate(msg, 0, msg.Length);
                    byte[] sig = signer.GenerateSignature();
                    return sig;
                }
                catch (Exception e)
                {
                    log.Error("SignSm3WithSm2Asn1Rs error: " + e.Message, e);
                    return null;
                }
            }
    
            /**
            *
            * @param msg
            * @param userId
            * @param rs r||s,直接拼接byte数组的rs
            * @param publicKey
            * @return
            */
            public static bool VerifySm3WithSm2(byte[] msg, byte[] userId, byte[] rs, AsymmetricKeyParameter publicKey)
            {
                if (rs == null || msg == null || userId == null) return false;
                if (rs.Length != RS_LEN * 2) return false;
                return VerifySm3WithSm2Asn1Rs(msg, userId, RsPlainByteArrayToAsn1(rs), publicKey);
            }
    
            /**
             *
             * @param msg
             * @param userId
             * @param rs in <b>asn1 format</b>
             * @param publicKey
             * @return
             */
    
            public static bool VerifySm3WithSm2Asn1Rs(byte[] msg, byte[] userId, byte[] sign, AsymmetricKeyParameter publicKey)
            {
                try
                {
                    ISigner signer = SignerUtilities.GetSigner("SM3withSM2");
                    signer.Init(false, new ParametersWithID(publicKey, userId));
                    signer.BlockUpdate(msg, 0, msg.Length);
                    return signer.VerifySignature(sign);
                }
                catch (Exception e)
                {
                    log.Error("VerifySm3WithSm2Asn1Rs error: " + e.Message, e);
                    return false;
                }
            }
    
            /**
             * bc加解密使用旧标c1||c2||c3,此方法在加密后调用,将结果转化为c1||c3||c2
             * @param c1c2c3
             * @return
             */
            private static byte[] ChangeC1C2C3ToC1C3C2(byte[] c1c2c3)
            {
                int c1Len = (x9ECParameters.Curve.FieldSize + 7) / 8 * 2 + 1; //sm2p256v1的这个固定65。可看GMNamedCurves、ECCurve代码。
                const int c3Len = 32; //new SM3Digest().getDigestSize();
                byte[] result = new byte[c1c2c3.Length];
                Buffer.BlockCopy(c1c2c3, 0, result, 0, c1Len); //c1
                Buffer.BlockCopy(c1c2c3, c1c2c3.Length - c3Len, result, c1Len, c3Len); //c3
                Buffer.BlockCopy(c1c2c3, c1Len, result, c1Len + c3Len, c1c2c3.Length - c1Len - c3Len); //c2
                return result;
            }
    
    
            /**
             * bc加解密使用旧标c1||c3||c2,此方法在解密前调用,将密文转化为c1||c2||c3再去解密
             * @param c1c3c2
             * @return
             */
            private static byte[] ChangeC1C3C2ToC1C2C3(byte[] c1c3c2)
            {
                int c1Len = (x9ECParameters.Curve.FieldSize + 7) / 8 * 2 + 1; //sm2p256v1的这个固定65。可看GMNamedCurves、ECCurve代码。
                const int c3Len = 32; //new SM3Digest().GetDigestSize();
                byte[] result = new byte[c1c3c2.Length];
                Buffer.BlockCopy(c1c3c2, 0, result, 0, c1Len); //c1: 0->65
                Buffer.BlockCopy(c1c3c2, c1Len + c3Len, result, c1Len, c1c3c2.Length - c1Len - c3Len); //c2
                Buffer.BlockCopy(c1c3c2, c1Len, result, c1c3c2.Length - c3Len, c3Len); //c3
                return result;
            }
    
            /**
             * c1||c3||c2
             * @param data
             * @param key
             * @return
             */
            public static byte[] Sm2Decrypt(byte[] data, AsymmetricKeyParameter key)
            {
                return Sm2DecryptOld(ChangeC1C3C2ToC1C2C3(data), key);
            }
    
            /**
             * c1||c3||c2
             * @param data
             * @param key
             * @return
             */
    
            public static byte[] Sm2Encrypt(byte[] data, AsymmetricKeyParameter key)
            {
                return ChangeC1C2C3ToC1C3C2(Sm2EncryptOld(data, key));
            }
    
            /**
             * c1||c2||c3
             * @param data
             * @param key
             * @return
             */
            public static byte[] Sm2EncryptOld(byte[] data, AsymmetricKeyParameter pubkey)
            {
                try
                {
                    SM2Engine sm2Engine = new SM2Engine();
                    sm2Engine.Init(true, new ParametersWithRandom(pubkey, new SecureRandom()));
                    return sm2Engine.ProcessBlock(data, 0, data.Length);
                }
                catch (Exception e)
                {
                    log.Error("Sm2EncryptOld error: " + e.Message, e);
                    return null;
                }
            }
    
            /**
             * c1||c2||c3
             * @param data
             * @param key
             * @return
             */
            public static byte[] Sm2DecryptOld(byte[] data, AsymmetricKeyParameter key)
            {
                try
                {
                    SM2Engine sm2Engine = new SM2Engine();
                    sm2Engine.Init(false, key);
                    return sm2Engine.ProcessBlock(data, 0, data.Length);
                }
                catch (Exception e)
                {
                    log.Error("Sm2DecryptOld error: " + e.Message, e);
                    return null;
                }
            }
    
            /**
             * @param bytes
             * @return
             */
            public static byte[] Sm3(byte[] bytes)
            {
                try
                {
                    SM3Digest digest = new SM3Digest();
                    digest.BlockUpdate(bytes, 0, bytes.Length);
                    byte[] result = DigestUtilities.DoFinal(digest);
                    return result;
                }
                catch (Exception e)
                {
                    log.Error("Sm3 error: " + e.Message, e);
                    return null;
                }
            }
    
            private const int RS_LEN = 32;
    
            private static byte[] BigIntToFixexLengthBytes(BigInteger rOrS)
            {
                // for sm2p256v1, n is 00fffffffeffffffffffffffffffffffff7203df6b21c6052b53bbf40939d54123,
                // r and s are the result of mod n, so they should be less than n and have length<=32
                byte[] rs = rOrS.ToByteArray();
                if (rs.Length == RS_LEN) return rs;
                else if (rs.Length == RS_LEN + 1 && rs[0] == 0) return Arrays.CopyOfRange(rs, 1, RS_LEN + 1);
                else if (rs.Length < RS_LEN)
                {
                    byte[] result = new byte[RS_LEN];
                    Arrays.Fill(result, (byte)0);
                    Buffer.BlockCopy(rs, 0, result, RS_LEN - rs.Length, rs.Length);
                    return result;
                }
                else
                {
                    throw new ArgumentException("err rs: " + Hex.ToHexString(rs));
                }
            }
    
            /**
             * BC的SM3withSM2签名得到的结果的rs是asn1格式的,这个方法转化成直接拼接r||s
             * @param rsDer rs in asn1 format
             * @return sign result in plain byte array
             */
            private static byte[] RsAsn1ToPlainByteArray(byte[] rsDer)
            {
                Asn1Sequence seq = Asn1Sequence.GetInstance(rsDer);
                byte[] r = BigIntToFixexLengthBytes(DerInteger.GetInstance(seq[0]).Value);
                byte[] s = BigIntToFixexLengthBytes(DerInteger.GetInstance(seq[1]).Value);
                byte[] result = new byte[RS_LEN * 2];
                Buffer.BlockCopy(r, 0, result, 0, r.Length);
                Buffer.BlockCopy(s, 0, result, RS_LEN, s.Length);
                return result;
            }
    
            /**
             * BC的SM3withSM2验签需要的rs是asn1格式的,这个方法将直接拼接r||s的字节数组转化成asn1格式
             * @param sign in plain byte array
             * @return rs result in asn1 format
             */
            private static byte[] RsPlainByteArrayToAsn1(byte[] sign)
            {
                if (sign.Length != RS_LEN * 2) throw new ArgumentException("err rs. ");
                BigInteger r = new BigInteger(1, Arrays.CopyOfRange(sign, 0, RS_LEN));
                BigInteger s = new BigInteger(1, Arrays.CopyOfRange(sign, RS_LEN, RS_LEN * 2));
                Asn1EncodableVector v = new Asn1EncodableVector();
                v.Add(new DerInteger(r));
                v.Add(new DerInteger(s));
                try
                {
                    return new DerSequence(v).GetEncoded("DER");
                }
                catch (IOException e)
                {
                    log.Error("RsPlainByteArrayToAsn1 error: " + e.Message, e);
                    return null;
                }
            }
    
            public static AsymmetricCipherKeyPair GenerateKeyPair()
            {
                try
                {
                    ECKeyPairGenerator kpGen = new ECKeyPairGenerator();
                    kpGen.Init(new ECKeyGenerationParameters(ecDomainParameters, new SecureRandom()));
                    return kpGen.GenerateKeyPair();
                }
                catch (Exception e)
                {
                    log.Error("generateKeyPair error: " + e.Message, e);
                    return null;
                }
            }
    
            public static ECPrivateKeyParameters GetPrivatekeyFromD(BigInteger d)
            {
                return new ECPrivateKeyParameters(d, ecDomainParameters);
            }
    
            public static ECPublicKeyParameters GetPublickeyFromXY(BigInteger x, BigInteger y)
            {
                return new ECPublicKeyParameters(x9ECParameters.Curve.CreatePoint(x, y), ecDomainParameters);
            }
    
            public static AsymmetricKeyParameter GetPublickeyFromX509File(FileInfo file)
            {
    
                FileStream fileStream = null;
                try
                {
                    //file.DirectoryName + "\\" + file.Name
                    fileStream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read);
                    X509Certificate certificate = new X509CertificateParser().ReadCertificate(fileStream);
                    return certificate.GetPublicKey();
                }
                catch (Exception e)
                {
                    log.Error(file.Name + "读取失败,异常:" + e);
                }
                finally
                {
                    if (fileStream != null)
                        fileStream.Close();
                }
                return null;
            }
    
            public class Sm2Cert
            {
                public AsymmetricKeyParameter privateKey;
                public AsymmetricKeyParameter publicKey;
                public String certId;
            }
    
            private static byte[] ToByteArray(int i)
            {
                byte[] byteArray = new byte[4];
                byteArray[0] = (byte)(i >> 24);
                byteArray[1] = (byte)((i & 0xFFFFFF) >> 16);
                byteArray[2] = (byte)((i & 0xFFFF) >> 8);
                byteArray[3] = (byte)(i & 0xFF);
                return byteArray;
            }
    
            /**
             * 字节数组拼接
             *
             * @param params
             * @return
             */
            private static byte[] Join(params byte[][] byteArrays)
            {
                List<byte> byteSource = new List<byte>();
                for (int i = 0; i < byteArrays.Length; i++)
                {
                    byteSource.AddRange(byteArrays[i]);
                }
                byte[] data = byteSource.ToArray();
                return data;
            }
    
            /**
             * 密钥派生函数
             *
             * @param Z
             * @param klen
             *            生成klen字节数长度的密钥
             * @return
             */
            private static byte[] KDF(byte[] Z, int klen)
            {
                int ct = 1;
                int end = (int)Math.Ceiling(klen * 1.0 / 32);
                List<byte> byteSource = new List<byte>();
                try
                {
                    for (int i = 1; i < end; i++)
                    {
                        byteSource.AddRange(GmUtil.Sm3(Join(Z, ToByteArray(ct))));
                        ct++;
                    }
                    byte[] last = GmUtil.Sm3(Join(Z, ToByteArray(ct)));
                    if (klen % 32 == 0)
                    {
                        byteSource.AddRange(last);
                    }
                    else
                        byteSource.AddRange(Arrays.CopyOfRange(last, 0, klen % 32));
                    return byteSource.ToArray();
                }
                catch (Exception e)
                {
                    log.Error("KDF error: " + e.Message, e);
                }
                return null;
            }
    
            public static byte[] Sm4DecryptCBC(byte[] keyBytes, byte[] cipher, byte[] iv, String algo)
            {
                if (keyBytes.Length != 16) throw new ArgumentException("err key length");
                if (cipher.Length % 16 != 0) throw new ArgumentException("err data length");
    
                try
                {
                    KeyParameter key = ParameterUtilities.CreateKeyParameter("SM4", keyBytes);
                    IBufferedCipher c = CipherUtilities.GetCipher(algo);
                    if (iv == null) iv = ZeroIv(algo);
                    c.Init(false, new ParametersWithIV(key, iv));
                    return c.DoFinal(cipher);
                }
                catch (Exception e)
                {
                    log.Error("Sm4DecryptCBC error: " + e.Message, e);
                    return null;
                }
            }
    
    
            public static byte[] Sm4EncryptCBC(byte[] keyBytes, byte[] plain, byte[] iv, String algo)
            {
                if (keyBytes.Length != 16) throw new ArgumentException("err key length");
                if (plain.Length % 16 != 0) throw new ArgumentException("err data length");
    
                try
                {
                    KeyParameter key = ParameterUtilities.CreateKeyParameter("SM4", keyBytes);
                    IBufferedCipher c = CipherUtilities.GetCipher(algo);
                    if (iv == null) iv = ZeroIv(algo);
                    c.Init(true, new ParametersWithIV(key, iv));
                    return c.DoFinal(plain);
                }
                catch (Exception e)
                {
                    log.Error("Sm4EncryptCBC error: " + e.Message, e);
                    return null;
                }
            }
    
            private static byte[] padding(byte[] input)
            {
                if (input == null)
                {
                    return null;
                }
    
                byte[] ret = (byte[])null;
         
                    int p = 16 - input.Length % 16;
                    ret = new byte[input.Length + p];
                    Array.Copy(input, 0, ret, 0, input.Length);
                    for (int i = 0; i < p; i++)
                    {
                        ret[input.Length + i] = (byte)p;
                    }
              
                return ret;
            }
            public static byte[] Sm4EncryptECB(byte[] keyBytes, byte[] plain, string algo)
            {
                if (keyBytes.Length != 16) throw new ArgumentException("err key length");
                // if (plain.Length % 16 != 0) throw new ArgumentException("err data length");
                plain = padding(plain);
                try
                {
                    KeyParameter key = ParameterUtilities.CreateKeyParameter("SM4", keyBytes);
                    IBufferedCipher c = CipherUtilities.GetCipher(algo);
                    c.Init(true, key);
                    return c.DoFinal(plain);
                }
                catch (Exception e)
                {
                    log.Error("Sm4EncryptECB error: " + e.Message, e);
                    return null;
                }
            }
    
            public static byte[] Sm4DecryptECB(byte[] keyBytes, byte[] cipher, string algo)
            {
                if (keyBytes.Length != 16) throw new ArgumentException("err key length");
                if (cipher.Length % 16 != 0) throw new ArgumentException("err data length");
    
                try
                {
                    KeyParameter key = ParameterUtilities.CreateKeyParameter("SM4", keyBytes);
                    IBufferedCipher c = CipherUtilities.GetCipher(algo);
                    c.Init(false, key);
                    return c.DoFinal(cipher);
                }
                catch (Exception e)
                {
                    log.Error("Sm4DecryptECB error: " + e.Message, e);
                    return null;
                }
            }
    
            public const String SM4_ECB_NOPADDING = "SM4/ECB/NoPadding";
            public const String SM4_CBC_NOPADDING = "SM4/CBC/NoPadding";
            public const String SM4_CBC_PKCS7PADDING = "SM4/CBC/PKCS7Padding";
    
            /**
             * cfca官网CSP沙箱导出的sm2文件
             * @param pem 二进制原文
             * @param pwd 密码
             * @return
             */
            public static Sm2Cert readSm2File(byte[] pem, String pwd)
            {
    
                Sm2Cert sm2Cert = new Sm2Cert();
                try
                {
                    Asn1Sequence asn1Sequence = (Asn1Sequence)Asn1Object.FromByteArray(pem);
                    //	    	ASN1Integer asn1Integer = (ASN1Integer) asn1Sequence.getObjectAt(0); //version=1
                    Asn1Sequence priSeq = (Asn1Sequence)asn1Sequence[1];//private key
                    Asn1Sequence pubSeq = (Asn1Sequence)asn1Sequence[2];//public key and x509 cert
    
                    //	    	ASN1ObjectIdentifier sm2DataOid = (ASN1ObjectIdentifier) priSeq.getObjectAt(0);
                    //	    	ASN1ObjectIdentifier sm4AlgOid = (ASN1ObjectIdentifier) priSeq.getObjectAt(1);
                    Asn1OctetString priKeyAsn1 = (Asn1OctetString)priSeq[2];
                    byte[] key = KDF(System.Text.Encoding.UTF8.GetBytes(pwd), 32);
                    byte[] priKeyD = Sm4DecryptCBC(Arrays.CopyOfRange(key, 16, 32),
                            priKeyAsn1.GetOctets(),
                            Arrays.CopyOfRange(key, 0, 16), SM4_CBC_PKCS7PADDING);
                    sm2Cert.privateKey = GetPrivatekeyFromD(new BigInteger(1, priKeyD));
                    //	    	log.Info(Hex.toHexString(priKeyD));
    
                    //	    	ASN1ObjectIdentifier sm2DataOidPub = (ASN1ObjectIdentifier) pubSeq.getObjectAt(0);
                    Asn1OctetString pubKeyX509 = (Asn1OctetString)pubSeq[1];
                    X509Certificate x509 = (X509Certificate)new X509CertificateParser().ReadCertificate(pubKeyX509.GetOctets());
                    sm2Cert.publicKey = x509.GetPublicKey();
                    sm2Cert.certId = x509.SerialNumber.ToString(10); //这里转10进账,有啥其他进制要求的自己改改
                    return sm2Cert;
                }
                catch (Exception e)
                {
                    log.Error("readSm2File error: " + e.Message, e);
                    return null;
                }
            }
    
            /**
             *
             * @param cert
             * @return
             */
            public static Sm2Cert ReadSm2X509Cert(byte[] cert)
            {
                Sm2Cert sm2Cert = new Sm2Cert();
                try
                {
    
                    X509Certificate x509 = new X509CertificateParser().ReadCertificate(cert);
                    sm2Cert.publicKey = x509.GetPublicKey();
                    sm2Cert.certId = x509.SerialNumber.ToString(10); //这里转10进账,有啥其他进制要求的自己改改
                    return sm2Cert;
                }
                catch (Exception e)
                {
                    log.Error("ReadSm2X509Cert error: " + e.Message, e);
                    return null;
                }
            }
    
            public static byte[] ZeroIv(String algo)
            {
    
                try
                {
                    IBufferedCipher cipher = CipherUtilities.GetCipher(algo);
                    int blockSize = cipher.GetBlockSize();
                    byte[] iv = new byte[blockSize];
                    Arrays.Fill(iv, (byte)0);
                    return iv;
                }
                catch (Exception e)
                {
                    log.Error("ZeroIv error: " + e.Message, e);
                    return null;
                }
            }
    
            public static void Main2(string[] s)
            {
    
                // 随便看看
                log.Info("GMNamedCurves: ");
                foreach (string e in GMNamedCurves.Names)
                {
                    log.Info(e);
                }
                log.Info("sm2p256v1 n:" + x9ECParameters.N);
                log.Info("sm2p256v1 nHex:" + Hex.ToHexString(x9ECParameters.N.ToByteArray()));
    
                // 生成公私钥对 ---------------------
                AsymmetricCipherKeyPair kp = GmUtil.GenerateKeyPair();
                log.Info("private key d: " + ((ECPrivateKeyParameters)kp.Private).D);
                log.Info("public key q:" + ((ECPublicKeyParameters)kp.Public).Q); //{x, y, zs...}
    
                //Key
                SM2Param sM2Param = new SM2Param();
                byte[] priKey = Convert.FromBase64String("DENOZDuuon+lHJCNzLyMfwJT8ZSdCcyPeW6JnWWkObo=");
                byte[] pubKey = Convert.FromBase64String("BGUh0gYeUj9WMa15L+QC0P62gJtX6JCrdIAIz96c5dGN6FbtxU7frc2qnL9IhogoHQgO8pt7A3ICSxmgJqiLERc=");
                ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(new BigInteger(1, priKey), sM2Param.ecc_bc_spec);
                ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(sM2Param.ecc_curve.DecodePoint(pubKey), sM2Param.ecc_bc_spec);
    
    
                //签名验签
                byte[] msg = System.Text.Encoding.UTF8.GetBytes("1");
                byte[] userId = System.Text.Encoding.UTF8.GetBytes("AA00EDC7ACB9F2CB");
                byte[] sig = SignSm3WithSm2(msg, userId, privateKeyParameters);
                string ss = Hex.ToHexString(sig);
                string result = Convert.ToBase64String(sig);
                string mw = "VkwmhDwtCaiqkLQAvM1tKnrb2KaqRps5mffBs4fEOCGNrosbf6dn/kJ+P4wyyZdahf+CvCB62Y5U4e2BPePhlw==";
                sig = Convert.FromBase64String(mw);
                bool b = GmUtil.VerifySm3WithSm2(msg, userId, sig, publicKeyParameters);// kp.Public);
            }
    
                /*/ 由d生成私钥 ---------------------
                BigInteger d = new BigInteger("097b5230ef27c7df0fa768289d13ad4e8a96266f0fcb8de40d5942af4293a54a", 16);
                ECPrivateKeyParameters bcecPrivateKey = GetPrivatekeyFromD(d);
                log.Info("testGetFromD: " + bcecPrivateKey.D.ToString(16));
    
                //公钥X坐标PublicKeyXHex: 59cf9940ea0809a97b1cbffbb3e9d96d0fe842c1335418280bfc51dd4e08a5d4
                //公钥Y坐标PublicKeyYHex: 9a7f77c578644050e09a9adc4245d1e6eba97554bc8ffd4fe15a78f37f891ff8
                AsymmetricKeyParameter publicKey = GetPublickeyFromX509File(new FileInfo("d:/certs/69629141652.cer"));
                log.Info(publicKey);
                AsymmetricKeyParameter publicKey1 = GetPublickeyFromXY(new BigInteger("59cf9940ea0809a97b1cbffbb3e9d96d0fe842c1335418280bfc51dd4e08a5d4", 16), new BigInteger("9a7f77c578644050e09a9adc4245d1e6eba97554bc8ffd4fe15a78f37f891ff8", 16));
                log.Info("testReadFromX509File: " + ((ECPublicKeyParameters)publicKey).Q);
                log.Info("testGetFromXY: " + ((ECPublicKeyParameters)publicKey1).Q);
                log.Info("testPubKey: " + publicKey.Equals(publicKey1));
                log.Info("testPubKey: " + ((ECPublicKeyParameters)publicKey).Q.Equals(((ECPublicKeyParameters)publicKey1).Q));
    
                // sm2 encrypt and decrypt test ---------------------
                AsymmetricCipherKeyPair kp2 = GenerateKeyPair();
                AsymmetricKeyParameter publicKey2 = kp2.Public;
                AsymmetricKeyParameter privateKey2 = kp2.Private;
                byte[] bs = Sm2Encrypt(System.Text.Encoding.UTF8.GetBytes("s"), publicKey2);
                log.Info("testSm2Enc dec: " + Hex.ToHexString(bs));
                bs = Sm2Decrypt(bs, privateKey2);
                log.Info("testSm2Enc dec: " + System.Text.Encoding.UTF8.GetString(bs));
    
                // sm4 encrypt and decrypt test ---------------------
                //0123456789abcdeffedcba9876543210 + 0123456789abcdeffedcba9876543210 -> 681edf34d206965e86b3e94f536e4246
                byte[] plain = Hex.Decode("0123456789abcdeffedcba98765432100123456789abcdeffedcba98765432100123456789abcdeffedcba9876543210");
                byte[] key = Hex.Decode("0123456789abcdeffedcba9876543210");
                byte[] cipher = Hex.Decode("595298c7c6fd271f0402f804c33d3f66");
                bs = Sm4EncryptECB(key, plain, GmUtil.SM4_ECB_NOPADDING);
                log.Info("testSm4EncEcb: " + Hex.ToHexString(bs)); ;
                bs = Sm4DecryptECB(key, bs, GmUtil.SM4_ECB_NOPADDING);
                log.Info("testSm4DecEcb: " + Hex.ToHexString(bs));
    
                //读.sm2文件
                String sm2 = "MIIDHQIBATBHBgoqgRzPVQYBBAIBBgcqgRzPVQFoBDDW5/I9kZhObxXE9Vh1CzHdZhIhxn+3byBU\nUrzmGRKbDRMgI3hJKdvpqWkM5G4LNcIwggLNBgoqgRzPVQYBBAIBBIICvTCCArkwggJdoAMCAQIC\nBRA2QSlgMAwGCCqBHM9VAYN1BQAwXDELMAkGA1UEBhMCQ04xMDAuBgNVBAoMJ0NoaW5hIEZpbmFu\nY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEbMBkGA1UEAwwSQ0ZDQSBURVNUIFNNMiBPQ0Ex\nMB4XDTE4MTEyNjEwMTQxNVoXDTIwMTEyNjEwMTQxNVowcjELMAkGA1UEBhMCY24xEjAQBgNVBAoM\nCUNGQ0EgT0NBMTEOMAwGA1UECwwFQ1VQUkExFDASBgNVBAsMC0VudGVycHJpc2VzMSkwJwYDVQQD\nDCAwNDFAWnRlc3RAMDAwMTAwMDA6U0lHTkAwMDAwMDAwMTBZMBMGByqGSM49AgEGCCqBHM9VAYIt\nA0IABDRNKhvnjaMUShsM4MJ330WhyOwpZEHoAGfqxFGX+rcL9x069dyrmiF3+2ezwSNh1/6YqfFZ\nX9koM9zE5RG4USmjgfMwgfAwHwYDVR0jBBgwFoAUa/4Y2o9COqa4bbMuiIM6NKLBMOEwSAYDVR0g\nBEEwPzA9BghggRyG7yoBATAxMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmNmY2EuY29tLmNuL3Vz\nL3VzLTE0Lmh0bTA4BgNVHR8EMTAvMC2gK6AphidodHRwOi8vdWNybC5jZmNhLmNvbS5jbi9TTTIv\nY3JsNDI4NS5jcmwwCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBREhx9VlDdMIdIbhAxKnGhPx8FcHDAd\nBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwDAYIKoEcz1UBg3UFAANIADBFAiEAgWvQi3h6\niW4jgF4huuXfhWInJmTTYr2EIAdG8V4M8fYCIBixygdmfPL9szcK2pzCYmIb6CBzo5SMv50Odycc\nVfY6";
                bs = Convert.FromBase64String(sm2);
                String pwd = "cfca1234";
                GmUtil.Sm2Cert sm2Cert = GmUtil.readSm2File(bs, pwd);
                log.Info("testReadSm2File, pubkey: " + ((ECPublicKeyParameters)sm2Cert.publicKey).Q.ToString());
                log.Info("testReadSm2File, prikey: " + Hex.ToHexString(((ECPrivateKeyParameters)sm2Cert.privateKey).D.ToByteArray()));
                log.Info("testReadSm2File, certId: " + sm2Cert.certId);
    
                bs = Sm2Encrypt(System.Text.Encoding.UTF8.GetBytes("s"), ((ECPublicKeyParameters)sm2Cert.publicKey));
                log.Info("testSm2Enc dec: " + Hex.ToHexString(bs));
                bs = Sm2Decrypt(bs, ((ECPrivateKeyParameters)sm2Cert.privateKey));
                log.Info("testSm2Enc dec: " + System.Text.Encoding.UTF8.GetString(bs));
    
                msg = System.Text.Encoding.UTF8.GetBytes("message digest");
                userId = System.Text.Encoding.UTF8.GetBytes("userId");
                sig = SignSm3WithSm2(msg, userId, ((ECPrivateKeyParameters)sm2Cert.privateKey));
                log.Info("testSignSm3WithSm2: " + Hex.ToHexString(sig));
                log.Info("testVerifySm3WithSm2: " + VerifySm3WithSm2(msg, userId, sig, ((ECPublicKeyParameters)sm2Cert.publicKey)));
            }
               
                ///*/
    
            }
        }
    
    
    

    经实践签名验签成功,感谢大佬分享!

    展开全文
  • SM2签名验签实现

    千次阅读 2020-08-20 10:55:12
    转发来自:https://github.com/hwyqb/SM2_SM3_SM4Encrypt 需要注意的就是 1.明文转16进制不要直接getBytes,先base64转码后再16进制转换 2.大小写和加密机统一,要么全大写,要么全小写。

    转发来自链接: https://github.com/hwyqb/SM2_SM3_SM4Encrypt
    需要注意的就是
    1.明文转16进制不要直接getBytes,先base64转码后再16进制转换
    2.大小写和加密机统一,要么全大写,要么全小写。

    展开全文
  • 如题需求,没弄过SM2,求助下,自己想办法时间上来不及了。求个好用的2021吉林省医保C#SM2签名实现的demo。
  • 国密算法sm实现 sm2数字签名 密钥交换,sm3,sm4,已实现、求sm2第四部分公钥加密c实现源码。。。江湖救急。。。
  • 最近在工作中遇到一个需求:签名者使用密码设备(如加密机)生成了一些 SM2 签名,现在用户需要对签名进行验证,可是验签方没有密码设备,验签必须使用软件实现。在 CSDN 上找到了 goldboar 写的 SM2 签名及验签函数()...

    最近在工作中遇到一个需求:签名者使用密码设备(如加密机)生成了一些 SM2 签名,现在用户需要对签名进行验证,可是验签方没有密码设备,验签必须使用软件实现。在 CSDN 上找到了 goldboar 写的 SM2 签名及验签函数(

    ),但是不能直接使用。原因如下:

    1) goldboar 的程序是自己生成 SM2 密钥对,用密钥对产生签名再验证签名,而现在需要使用外部传入的公钥、签名来做验签;

    2) goldboar 的程序中使用的 ECC 参数是示例参数,不是 GM/T 0003.5-2019 规范中定义的参数;

    3) goldboar 的程序是示例程序,没有对动态分配的内存进行仔细地清理,内存泄漏量不少。

    在《密码设备应用接口规范》中,对 SM2 公钥的数据结构定义如下:

    #define  ECCref_MAX_BITS   512

    #define  ECCref_MAX_LEN  ((ECCref_MAX_BITS+7) / 8)

    typedef struct ECCrefPublicKey_st

    {

    unsigned int  bits;

    unsigned char  x[ECCref_MAX_LEN];

    unsigned char  y[ECCref_MAX_LEN];

    } ECCrefPublicKey;

    对 SM2 签名的数据结构定义如下:

    typedef struct ECCSignature_st

    {

    unsigned char  r[ECCref_MAX_LEN];

    unsigned char  s[ECCref_MAX_LEN];

    } ECCSignature;

    可以看出公钥和签名都是以坐标分量的形式给出的。现在已经有以下信息:对原始数据的 SM3 哈希值(已经过预处理,对预处理的介绍可以看

    )、SM2 公钥、SM2 签名,要根据这些信息来验证签名。

    于是在 goldboar 写的 SM2 程序的基础上,改写了一个纯粹用来做 SM2 签名验证的函数,编译时需要用到OpenSSL的头文件和库文件(libeay32.lib或libeay32.dll)。与 goldboar 的程序区别如下:

    1) 仅用于做验签,不能签名;

    2) 验签使用外部传入的 SM2 公钥,SM2 公钥以 (x,y) 坐标形式传入;

    3) 签名也是以 (r,s) 坐标形式传入;

    4) 增加了一些内存清理语句,内存泄漏有改善;

    5) 验签函数中采用的椭圆曲线参数是规范 GM/T 0003.5-2019 中定义的参数。

    6) 将一些对椭圆曲线参数的验证操作放入 _DEBUG 宏限制的范围内。因为参数是规范推荐的,已经过验证,所以在程序中无需再验证。将这些验证语句放入 _DEBUG 宏限制的范围内以后,如果编译 release 版本时就不会包含这些验证语句,效率可以有一点提升。

    调用OpenSSL的椭圆曲线运算函数以后,总是会有一点内存泄漏,OpenSSL官方对于内存泄漏在网页

    上是这样解释的:

    I think I‘ve detected a memory leak, is this a bug?

    In most cases the cause of an apparent memory leak is an OpenSSL internal table that is allocated when an application starts up. Since such tables do not grow in size over time they are harmless.

    从中可以看出,只要内存泄漏不随着调用函数次数的增加而增加,就不用担心。于是在 SM2 签名验签函数的基础上又写了一个测试函数,实验后发现如果反复验签多次,与只做一次验签相比,产生的内存泄漏数量没有增长,这就算是可以接受了。

    SM2 签名验签函数的下载网址是:

    C语言实现的SM2数字签名验证,布布扣,bubuko.com

    C语言实现的SM2数字签名验证

    展开全文
  • sm2数字签名算法python实现
  • 关于SM2签名算法的实现

    千次阅读 2020-02-29 11:50:06
    国密标准的SM2签名算法,并不是简单的将明文通过SM3算法Hash,再将Hash结果通过SM2算法使用私钥进行签名。 Hash这块比较复杂,要经过两次SM3算法进行Hash。 中间还有Za参与运算。 第一次Hash其实只是对Za的Hash,Za...
  • C#编写的exe工具,可实现SM2签名验签,SM4加解密,100%适用于黑龙江省国家医保接口中进行应用。 操作方式:使用编译程序调用exe工具,exe工具将结果写入目录SM2SM4.txt中,再读取txt内容即可。 提供给第三方无法实现...
  • SM2签名验签C语言实现

    2017-10-27 09:03:30
    国密SM2签名验签C语言实现及测试例子 国密SM2签名验签C语言实现及测试例子
  • 虽然都是国密算法SM2,但是随着厂商不一样,每个厂商的使用方法不一样,导致SM2签名结果不一致,今天就给大家介绍一些示例,都是各种对接过程中的存货,会拆分成几个文章进行讲解。为了确保安全,示例中的密钥会使用...
  • c# sm2签名
  • arithmetic.o 文件 515 2012-03-19 16:29 yl_sm2_gmp\Debug\src\sm2_func.d 文件 37056 2012-03-19 16:29 yl_sm2_gmp\Debug\src\sm2_func.o 文件 985 2012-03-19 16:29 yl_sm2_gmp\Debug\src\subdir.mk ...
  • 国密算法SM2签名、SM2验证签名示例(二);SM2模式与ASN1区别在于签名值长度不一样。
  • SM2 签名预处理操作

    千次阅读 2020-06-13 16:31:36
    一般情况下,计算数字签名时应执行以下操作: 1. 计算原始数据的 Hash 值; 2. 将 Hash 值作为输入,计算签名函数的输出。并不是对原始数据直接签名,而是对 Hash 值签名。 验证签名时应执行以下操作: 1. 计算...
  • python实现F2^m域sm2签名与验签算法,包含sm3杂凑算法,不调用其他库,完全自主实现,已通过测试,可直接使用,方便初学者对sm2算法进行学习研究。 完全按照国家密码局发布的《SM2椭圆曲线公钥密码算法》进行实现,...
  • 通过对 SM2 数字签名算法的改进,实现了代理者代表原始签名者的代理签名;安全分析表明,设计的算法具有可验证性、可识别性、可区分性、不可否认性和强不可伪造性。最后,利用C语言及Polarssl库对该方案进行了实现,...
  • 基于SM2签名的批验签高效实现方案.docx
  • 实现算法的 Engine专栏 本专栏订阅后可查看以下文章 1、基于OpenSSL,实现RSA使用的hash的ASN1编码转换 2、基于OpenSSL,实现RSA公钥的ASN1编码转换 3、实现SM2公私钥的格式转换 4、基于OpenSSL,实现SM2签名数据的...
  • 基于MIRACL大数库实现的国密2非对称加密解密、签名验签工具,使用Delphi 7编写

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,058
精华内容 823
关键字:

sm2签名实现