Browse Source

SM2修改

fuchaoyang 9 months ago
parent
commit
ad506640fa
3 changed files with 121 additions and 67 deletions
  1. 21 9
      SMTest/Program.cs
  2. 99 57
      YS.SM2/SM2Utils.cs
  3. 1 1
      YS.SM2/YS.SM2.csproj

+ 21 - 9
SMTest/Program.cs

@@ -1,20 +1,32 @@
 // See https://aka.ms/new-console-template for more information
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Utilities.Encoders;
+using System.Security.Cryptography.X509Certificates;
 using System.Text;
 using YS.SM2;
 using YS.SM3;
 
 Console.WriteLine("Hello, World!");
 #region SM2加解密
-var (publicKey, privateKey) = SM2Utils.GenerateKeyPair();
-var (publicKey1, privateKey1) = SM2Utils.GenerateKeyPair();
-Console.WriteLine(publicKey== publicKey1);
-Console.WriteLine(privateKey == privateKey1);
-var sm2Data = "123456789";
-var encryptSM2 = sm2Data.EncryptSM2(publicKey);
-Console.WriteLine($"SM2密文:{encryptSM2}");
-var decryptSM2 = encryptSM2.DecryptSM2(privateKey);
-Console.WriteLine($"SM2明文:{decryptSM2}");
+var sm2 = new SM2Utils();
+var asymmetric = sm2.GenerateKeyPair();
+var @public = (ECPublicKeyParameters)asymmetric.Public;
+var @private = (ECPrivateKeyParameters)asymmetric.Private;
+
+string publicKeyHex = Hex.ToHexString(@public.Q.GetEncoded());
+string privateKeyHex = @private.D.ToString(16);
+
+Console.WriteLine(  $"公钥:{publicKeyHex}");
+Console.WriteLine($"私钥:{privateKeyHex}");
+var text = "我一个无情铁手然后A接W一个外圈刮";
+var bty=Encoding.UTF8.GetBytes(text);
+var btyEncr = sm2.Encrypt(text, publicKeyHex);
+
+var cod=sm2.Decrypt(btyEncr, privateKeyHex);
+//var res = Encoding.UTF8.GetString(cod);
+Console.WriteLine(cod);
+Console.ReadLine();
 #endregion
 #region SM3加密
 //var sm3Data = "123456789";

+ 99 - 57
YS.SM2/SM2Utils.cs

@@ -3,87 +3,129 @@ using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Utilities.Encoders;
 using System.Text;
-using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Asn1.GM;
+using Org.BouncyCastle.Crypto.Generators;
 
 namespace YS.SM2
 {
     /// <summary>
     /// SM2加解密
     /// </summary>
-    public static class SM2Utils
+    public class SM2Utils
     {
+        private readonly ECDomainParameters ecParams;
+        private readonly SecureRandom secureRandom;
         /// <summary>
-        /// 获取公钥和私钥
+        /// SM2
         /// </summary>
-        public static (string, string) GenerateKeyPair()
+        public SM2Utils()
         {
-            SM2Provider sm2 = SM2Provider.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;
-            var _publicKey = Encoding.Default.GetString(Hex.Encode(publicKey.GetEncoded())).ToUpper();
-            var _privateKey = Encoding.Default.GetString(Hex.Encode(privateKey.ToByteArray())).ToUpper();
-            Console.WriteLine($"公钥:{_publicKey}");
-            Console.WriteLine($"私钥: {_privateKey}");
-            return (_publicKey, _privateKey);
+            var curve = GMNamedCurves.GetByName("sm2p256v1");
+            ecParams = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H);
+            secureRandom = new SecureRandom();
+        }
+        /// <summary>
+        /// 生成密码
+        /// </summary>
+        /// <returns></returns>
+        public AsymmetricCipherKeyPair GenerateKeyPair()
+        {
+            ECKeyPairGenerator generator = new ECKeyPairGenerator();
+            KeyGenerationParameters keyGenParam = new ECKeyGenerationParameters(ecParams, secureRandom);
+            generator.Init(keyGenParam);
+            return generator.GenerateKeyPair();
         }
         /// <summary>
         /// 加密
         /// </summary>
+        /// <param name="data">需要加密的字节</param>
         /// <param name="publicKey">公钥</param>
-        /// <param name="data">需要加密的数据</param>
         /// <returns></returns>
-        public static string EncryptSM2(this string data, string publicKey)
+        /// <exception cref="ArgumentNullException"></exception>
+        public byte[] Encrypt(byte[] data, string publicKey)
         {
-            if (string.IsNullOrWhiteSpace(data))
-                return null;
-            if (string.IsNullOrWhiteSpace(publicKey))
-                return null;
-            var _data = Encoding.UTF8.GetBytes(data);
-            var _publicKey = Hex.Decode(publicKey);
-            var source = new byte[data.Length];
-            Array.Copy(_data, 0, source, 0, data.Length);
-            var cipher = new Cipher();
-            var sm2 = SM2Provider.Instance;
-            var userKey = sm2.Ecc_Curve.DecodePoint(_publicKey);
-            var c1 = cipher.Init_enc(sm2, userKey);
-            cipher.Encrypt(source);
-            var c3 = new byte[32];
-            cipher.Dofinal(c3);
-            var sc1 = Encoding.Default.GetString(Hex.Encode(c1.GetEncoded()));
-            var sc2 = Encoding.Default.GetString(Hex.Encode(source));
-            var sc3 = Encoding.Default.GetString(Hex.Encode(c3));
-            return (sc1 + sc2 + sc3).ToUpper();
+            if (data == null)
+                throw new ArgumentNullException(nameof(data));
+            if (publicKey == null)
+                throw new ArgumentNullException(nameof(publicKey));
+            var pub= ConvertHexToPublicKey(publicKey);
+            SM2Engine sm2Engine = new SM2Engine();
+            sm2Engine.Init(true, new ParametersWithRandom(pub, secureRandom));
+            return sm2Engine.ProcessBlock(data, 0, data.Length);
         }
         /// <summary>
         /// 解密
         /// </summary>
-        /// <param name="encryptedData">需要解密的数据</param>
+        /// <param name="encryptedData">需要解密的字节</param>
         /// <param name="privateKey">私钥</param>
         /// <returns></returns>
-        public static string DecryptSM2(this string encryptedData, string privateKey)
+        /// <exception cref="ArgumentNullException"></exception>
+        public byte[] Decrypt(byte[] encryptedData, string privateKey)
+        {
+            if (encryptedData == null)
+                throw new ArgumentNullException(nameof(encryptedData));
+            if (privateKey == null)
+                throw new ArgumentNullException(nameof(privateKey));
+            var pri = ConvertHexToPrivateKey(privateKey);
+            SM2Engine sm2Engine = new SM2Engine();
+            sm2Engine.Init(false, pri);
+            return sm2Engine.ProcessBlock(encryptedData, 0, encryptedData.Length);
+        }
+        /// <summary>
+        /// 字符串加密
+        /// </summary>
+        /// <param name="plainText">需要加密的字符串</param>
+        /// <param name="publicKeyHex">公钥</param>
+        /// <returns></returns>
+        /// <exception cref="ArgumentNullException"></exception>
+        public string Encrypt(string plainText, string publicKeyHex)
+        {
+            if (plainText == null)
+                throw new ArgumentNullException(nameof(plainText));
+            if (publicKeyHex == null)
+                throw new ArgumentNullException(nameof(publicKeyHex));
+            byte[] plainBytes = Encoding.UTF8.GetBytes(plainText);
+            byte[] encryptedBytes = Encrypt(plainBytes, publicKeyHex);
+            return Convert.ToBase64String(encryptedBytes);
+        }
+        /// <summary>
+        /// 字符串解密
+        /// </summary>
+        /// <param name="cipherText">需要解密的字符串</param>
+        /// <param name="privateKeyHex">私钥</param>
+        /// <returns></returns>
+        /// <exception cref="ArgumentNullException"></exception>
+        public string Decrypt(string cipherText, string privateKeyHex)
+        {
+            if (cipherText == null)
+                throw new ArgumentNullException(nameof(cipherText));
+            if (privateKeyHex == null)
+                throw new ArgumentNullException(nameof(privateKeyHex));
+            byte[] cipherBytes = Convert.FromBase64String(cipherText);
+            byte[] decryptedBytes = Decrypt(cipherBytes, privateKeyHex);
+            return Encoding.UTF8.GetString(decryptedBytes);
+        }
+        /// <summary>
+        /// 公钥转换
+        /// </summary>
+        /// <param name="publicKeyHex">公钥</param>
+        /// <returns></returns>
+        private ECPublicKeyParameters ConvertHexToPublicKey(string publicKeyHex)
+        {
+            var q = ecParams.Curve.DecodePoint(Hex.Decode(publicKeyHex));
+            return new ECPublicKeyParameters(q, ecParams);
+        }
+        /// <summary>
+        /// 私钥转换
+        /// </summary>
+        /// <param name="privateKeyHex">私钥</param>
+        /// <returns></returns>
+        private ECPrivateKeyParameters ConvertHexToPrivateKey(string privateKeyHex)
         {
-            if (string.IsNullOrWhiteSpace(encryptedData))
-                return null;
-            if (string.IsNullOrWhiteSpace(privateKey))
-                return null;
-            var _encryptedData = Hex.Decode(encryptedData);
-            var _privateKey = Hex.Decode(privateKey);
-            var data = Encoding.UTF8.GetString(Hex.Encode(_encryptedData));
-            var c1Bytes = Hex.Decode(Encoding.UTF8.GetBytes(data.Substring(0, 130)));
-            var c2Len = _encryptedData.Length - 97;
-            var c2 = Hex.Decode(Encoding.UTF8.GetBytes(data.Substring(130, 2 * c2Len)));
-            var c3 = Hex.Decode(Encoding.UTF8.GetBytes(data.Substring(130 + 2 * c2Len, 64)));
-            var sm2 = SM2Provider.Instance;
-            var userD = new BigInteger(1, _privateKey);
-            var c1 = sm2.Ecc_Curve.DecodePoint(c1Bytes);
-            var cipher = new Cipher();
-            cipher.Init_dec(userD, c1);
-            cipher.Decrypt(c2);
-            cipher.Dofinal(c3);
-            return Encoding.UTF8.GetString(c2);
+            var d = new BigInteger(privateKeyHex, 16);
+            return new ECPrivateKeyParameters(d, ecParams);
         }
     }
 }

+ 1 - 1
YS.SM2/YS.SM2.csproj

@@ -5,7 +5,7 @@
     <ImplicitUsings>enable</ImplicitUsings>
     <GenerateDocumentationFile>True</GenerateDocumentationFile>
     <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
-    <Version>1.0.0</Version>
+    <Version>2.0.0</Version>
   </PropertyGroup>
 
   <ItemGroup>