c# SM2 加解密

需引入 Portable.BouncyCastle
 public class SM2Util
 {
     public static void Test()
     {
         string generatePrivateKey = "";
         string generatePublicKey = "0469dae639cc62fc4813a565e73a6748632565fac43b796b4291d3361a5b4967c77253584e51324363fa3be54ecb07183fe3b367c506d35f7cced8958210514ce7";

         GenerateKeyHex(out generatePublicKey, out generatePrivateKey);
         string signTime = DateTimeOffset.Now.ToUnixTimeSeconds().ToString();
         var handle = new SM2Util(generatePublicKey, generatePrivateKey, SM2Util.Mode.C1C3C2);
         //加密
         var encrypted = handle.Encrypt(Encoding.UTF8.GetBytes(signTime));
         string sign = Hex.ToHexString(encrypted);
         //解密
         var original = handle.Decrypt(encrypted);
         string result = Encoding.UTF8.GetString(original);
     }

     public SM2Util(byte[] pubkey, byte[] privkey, Mode mode)
     {
         this.pubkey = pubkey;
         this.privkey = privkey;
         this.mode = mode;
     }
     public SM2Util(string pubkey, string privkey, Mode mode = Mode.C1C2C3, bool isPkcs8 = false)
     {
         if (!isPkcs8)
         {
             if (pubkey != null) this.pubkey = Decode(pubkey);
             if (privkey != null) this.privkey = Decode(privkey);
         }
         else
         {
             if (pubkey != null) this.pubkey = ((ECPublicKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(pubkey))).Q.GetEncoded();
             if (privkey != null) this.privkey = ((ECPrivateKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privkey))).D.ToByteArray();
         }
         this.mode = mode;
     }
     byte[] pubkey;
     byte[] privkey;
     Mode mode;
     ICipherParameters _privateKeyParameters;
     ICipherParameters PrivateKeyParameters
     {
         get
         {
             var r = _privateKeyParameters;
             if (r == null) r = _privateKeyParameters = new ECPrivateKeyParameters(new BigInteger(1, privkey), new ECDomainParameters(GMNamedCurves.GetByName("SM2P256V1")));
             return r;
         }
     }
     ICipherParameters _publicKeyParameters;
     ICipherParameters PublicKeyParameters
     {
         get
         {
             var r = _publicKeyParameters;
             if (r == null)
             {
                 var x9ec = GMNamedCurves.GetByName("SM2P256V1");
                 r = _publicKeyParameters = new ECPublicKeyParameters(x9ec.Curve.DecodePoint(pubkey), new ECDomainParameters(x9ec));
             }
             return r;
         }
     }

     public static void GenerateKeyHex(out string pubkey, out string privkey)
     {
         GenerateKey(out var a, out var b);
         pubkey = Hex.ToHexString(a);
         privkey = Hex.ToHexString(b);
     }
     public static void GenerateKey(out byte[] pubkey, out byte[] privkey)
     {
         //用于生成椭圆曲线加密算法
         var g = new ECKeyPairGenerator();
         g.Init(new ECKeyGenerationParameters(new ECDomainParameters(GMNamedCurves.GetByName("SM2P256V1")), new SecureRandom()));
         var k = g.GenerateKeyPair();
         pubkey = ((ECPublicKeyParameters)k.Public).Q.GetEncoded(false);
         privkey = ((ECPrivateKeyParameters)k.Private).D.ToByteArray();
     }

     public byte[] Decrypt(byte[] data)
     {
         if (mode == Mode.C1C3C2) data = C132ToC123(data);
         var sm2 = new SM2Engine(new SM3Digest());
         sm2.Init(false, this.PrivateKeyParameters);
         return sm2.ProcessBlock(data, 0, data.Length);
     }
     public byte[] Encrypt(byte[] data)
     {
         var sm2 = new SM2Engine(new SM3Digest());
         sm2.Init(true, new ParametersWithRandom(PublicKeyParameters));
         data = sm2.ProcessBlock(data, 0, data.Length);
         if (mode == Mode.C1C3C2) data = C123ToC132(data);
         return data;
     }
     public byte[] Sign(byte[] msg, byte[] id = null)
     {
         var sm2 = new SM2Signer(new SM3Digest());
         ICipherParameters cp;
         if (id != null) cp = new ParametersWithID(new ParametersWithRandom(PrivateKeyParameters), id);
         else cp = new ParametersWithRandom(PrivateKeyParameters);
         sm2.Init(true, cp);
         sm2.BlockUpdate(msg, 0, msg.Length);
         return sm2.GenerateSignature();
     }
     public bool VerifySign(byte[] msg, byte[] signature, byte[] id = null)
     {
         var sm2 = new SM2Signer(new SM3Digest());
         ICipherParameters cp;
         if (id != null) cp = new ParametersWithID(PublicKeyParameters, id);
         else cp = PublicKeyParameters;
         sm2.Init(false, cp);
         sm2.BlockUpdate(msg, 0, msg.Length);
         return sm2.VerifySignature(signature);
     }
     static byte[] C123ToC132(byte[] c1c2c3)
     {
         var gn = GMNamedCurves.GetByName("SM2P256V1");
         int c1Len = (gn.Curve.FieldSize + 7) / 8 * 2 + 1;
         int c3Len = 32;
         byte[] result = new byte[c1c2c3.Length];
         Array.Copy(c1c2c3, 0, result, 0, c1Len); //c1
         Array.Copy(c1c2c3, c1c2c3.Length - c3Len, result, c1Len, c3Len); //c3
         Array.Copy(c1c2c3, c1Len, result, c1Len + c3Len, c1c2c3.Length - c1Len - c3Len); //c2
         return result;
     }
     static byte[] C132ToC123(byte[] c1c3c2)
     {
         var gn = GMNamedCurves.GetByName("SM2P256V1");
         int c1Len = (gn.Curve.FieldSize + 7) / 8 * 2 + 1;
         int c3Len = 32;
         byte[] result = new byte[c1c3c2.Length];
         Array.Copy(c1c3c2, 0, result, 0, c1Len); //c1: 0->65
         Array.Copy(c1c3c2, c1Len + c3Len, result, c1Len, c1c3c2.Length - c1Len - c3Len); //c2
         Array.Copy(c1c3c2, c1Len, result, c1c3c2.Length - c3Len, c3Len); //c3
         return result;
     }
     static byte[] Decode(string key)
     {
         return Regex.IsMatch(key, "^[0-9a-f]+$", RegexOptions.IgnoreCase) ? Hex.Decode(key) : Convert.FromBase64String(key);
     }
     public enum Mode
     {
         C1C2C3, C1C3C2
     }
 }

 

posted @ 2024-01-03 10:47  凉生凉忆亦凉心  阅读(713)  评论(0编辑  收藏  举报