1.新建SM2Util类
public class SM2Util
{
/**
* 生成SM2秘钥对
* string[0] 公钥
* string[1] 私钥
*/
public static string[] GenerateKeyPair()
{
return SM2.GenerateKeyPair();
}
/**
* SM2签名
* data 签名的数据
* priKey 私钥
*/
public static string Sign(string data, string priKey)
{
SM2 sm2 = new SM2(priKey, null);
return sm2.Sign(data);
}
/**
* SM2签名
* sign 源数据
* pubKey 公钥
* sign 签名的数据
*/
public static bool verifySign(string msg, string pubKey, string sign)
{
SM2 sm2 = new SM2(null, pubKey);
return sm2.verifySign(msg, sign);
}
/**
* 加密
* 返回Base64字符串
* 公钥加密
* plainText 要加密的文本
* pubKey 公钥
*/
public static string encryptBase64(string plainText, string pubKey)
{
SM2 sm2 = new SM2(null, pubKey);
byte[] encryptByte = sm2.encrypt(Encoding.UTF8.GetBytes(plainText));
return Base64.ToBase64String(encryptByte);
}
/**
* 解密
* 私钥解密
* plainText 要加密的文本
* pubKey 公钥
*/
public static string decryptBase64(string plainText, string priKey)
{
SM2 sm2 = new SM2(priKey, null);
byte[] deCode = Base64.Decode(plainText);
byte[] decryptText = sm2.deceypt(deCode);
return Encoding.UTF8.GetString(decryptText);
}
}
2.新建SM2类
class SM2
{
private ECPrivateKeyParameters privateKeyParameters;
private ECPublicKeyParameters publicKeyParameters;
private SM2Param sm2Param;
public SM2(string priKey, string pubKey)
{
this.init(HexUtils.decode(priKey), HexUtils.decode(pubKey));
}
private void init(byte[] priKey, byte[] pubKey)
{
this.sm2Param = new SM2Param();
if (null != priKey && this.privateKeyParameters == null)
{
this.privateKeyParameters = new ECPrivateKeyParameters(new BigInteger(1, priKey), this.sm2Param.ecc_bc_spec);
}
if (null != pubKey && this.publicKeyParameters == null)
{
this.publicKeyParameters = new ECPublicKeyParameters(this.sm2Param.ecc_curve.DecodePoint(pubKey), this.sm2Param.ecc_bc_spec);
}
}
/**
* 加签
*/
public string Sign(string data)
{
byte[] msg = Encoding.UTF8.GetBytes(data);
SM2Signer sm2Signer = new SM2Signer();
sm2Signer.Init(true, this.privateKeyParameters);
sm2Signer.BlockUpdate(msg, 0, msg.Length);
return Base64.ToBase64String(sm2Signer.GenerateSignature());
}
/*
* 验签
*/
public bool verifySign(string data, string sign)
{
byte[] signBase64 = Base64.Decode(sign);
byte[] msgByte = Encoding.UTF8.GetBytes(data);
SM2Signer sm2Signer = new SM2Signer();
sm2Signer.Init(false, this.publicKeyParameters);
sm2Signer.BlockUpdate(msgByte, 0, msgByte.Length);
return sm2Signer.VerifySignature(signBase64);
}
/**
* 加密
*
*/
public byte[] encrypt(byte[] plainText)
{
SM2Engine engine = new SM2Engine();
engine.Init(true, new ParametersWithRandom(this.publicKeyParameters));
return engine.ProcessBlock(plainText, 0, plainText.Length);
}
/**
*
* 解密
*
*/
public byte[] deceypt(byte[] plainText)
{
byte[] plain = plainText;
SM2Engine engine = new SM2Engine();
engine.Init(false, this.privateKeyParameters);
return engine.ProcessBlock(plain, 0, plain.Length);
}
public static string[] GenerateKeyPair()
{
AsymmetricCipherKeyPair kPair = genCipherKeyPair();
ECPrivateKeyParameters ecPrivateKey = (ECPrivateKeyParameters)kPair.Private;
ECPublicKeyParameters ecPublicKey = (ECPublicKeyParameters)kPair.Public;
BigInteger priKey = ecPrivateKey.D;
ECPoint pubKey = ecPublicKey.Q;
byte[] priByte = priKey.ToByteArray();
byte[] pubByte = pubKey.GetEncoded(false);
if (priByte.Length == 33)
{
Console.WriteLine("private key size 33");
byte[] newPriByte = new byte[32];
Array.Copy(priByte, 1, newPriByte, 0, 32);
priByte = newPriByte;
}
string[] keyPairs = new string[] { Hex.ToHexString(pubByte), Hex.ToHexString(priByte) };
return keyPairs;
}
/**
* 生成引用
* */
private static AsymmetricCipherKeyPair genCipherKeyPair()
{
SM2Param ecc_param = new SM2Param();
ECDomainParameters ecDomainParamters = ecc_param.ecc_bc_spec;
ECKeyGenerationParameters ecGenParam = new ECKeyGenerationParameters(ecDomainParamters, new SecureRandom());
ECKeyPairGenerator ecKeyPairGenerator = new ECKeyPairGenerator();
ecKeyPairGenerator.Init(ecGenParam);
return ecKeyPairGenerator.GenerateKeyPair();
}
private 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);
}
}
}
3.新建HexUtils
class HexUtils
{
private const string pattern = "^[a-f0-9]+$";
public static bool isHex(string value)
{
if (null == value)
{
return false;
}
return System.Text.RegularExpressions.Regex.IsMatch(value, pattern);
}
public static byte[] decode(String str)
{
if (null == str)
{
return null;
}
if (isHex(str))
{
return hexStrToByte(str);
}
return Org.BouncyCastle.Utilities.Encoders.Base64.Decode(str);
}
public static byte[] hexStrToByte(String hexStr)
{
if ((null == hexStr) || (hexStr.Length == 0))
{
return null;
}
char[] hexData = hexStr.ToCharArray();
int len = hexData.Length;
if ((len & 0x1) != 0)
{
throw new SystemException("Odd number of characters.");
}
byte[] out1 = new byte[len >> 1];
int i = 0;
for (int j = 0; j < len; i++)
{
int f = toDigit(hexData[j], j) << 4;
j++;
f |= toDigit(hexData[j], j);
j++;
out1[i] = ((byte)(f & 0xFF));
}
return out1;
}
private static int toDigit(char ch, int index)
{
int digit = Convert.ToInt32(ch.ToString(), 16);
//int digit = Character.digit(ch, 16);
if (digit == -1)
{
throw new SystemException("Illegal hexadecimal character " + ch + " at index " + index);
}
return digit;
}
}
4.主函数
static void Main(string[] args)
{
String pubKey = "045b50327b39fe34374deeeaf44c1ed0f0bd7e20850c67ade650afdec125809fd8e499d3305d239864ef57af9218b490f204c33af1c31fd4a101d4989d579ec047";
String priKey = "4e643581e15cbfecbfbb57b401a7eae91b9aa1073561b20606f28a03df16eec2";
Console.WriteLine("公钥:" + pubKey);
Console.WriteLine("私钥:" + priKey);
Console.WriteLine("============================");
String input = "POST|/api/v1.0/payment/pay-result-query|1627787104425|{\"payCode\":\"CK000000000011222324470415459\"}";
Console.WriteLine("input:" + input);
String sign = SM2Util.Sign(input, priKey);
Console.WriteLine("sign:" + sign);
Boolean success = SM2Util.verifySign(input, pubKey, sign);
Console.WriteLine("success:" + success);
Console.WriteLine("============================");
String input2 = "湘A88888";
String encrypt = SM2Util.encryptBase64(input2, pubKey);
Console.WriteLine("encrypt:" + encrypt);
String decrypt = SM2Util.decryptBase64(encrypt, priKey);
Console.WriteLine("decrypt:" + decrypt);
}
5.引入BouncyCastle.Crypto.dll动态库 注意动态库不同版本加密代码不一样*****
BouncyCastle.Crypto.dll动态库下载 https://files.cnblogs.com/files/ywtssydm/BouncyCastle.Crypto.rar?t=1692167684&download=true
完整代码下载: https://files.cnblogs.com/files/ywtssydm/CSharpDemo.zip?t=1692168492&download=true
更多资料:https://blog.csdn.net/a497785609/article/details/129102042
完整代码下载2:https://files.cnblogs.com/files/ywtssydm/sm2.rar?t=1692168765&download=true