C#SM2加密算法
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