|
@@ -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);
|
|
|
}
|
|
|
}
|
|
|
}
|