国密 SM2 加解密(C# / BouncyCastle)
直接回答 :在 .NET 里用国密 SM2,直接引 BouncyCastle.Cryptography 即可:先生成密钥对,加密用公钥、解密用私钥,签名验签同理;注意密钥和密文在传输时要统一用 Base64 还是 Hex。
SM2 是国家密码管理局组织制定并提出的椭圆曲线密码算法标准。
本文使用第三方密码库 BouncyCastle 实现 SM2 加解密,使用 NuGet 安装即可,包名:BouncyCastle.Cryptography,目前最新版本为:2.2.1 。
SM2 密钥对生成 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public static void GenerateSM2KeyPair (out string privateKey, out string publicKey ){ X9ECParameters curve = ECNamedCurveTable.GetByName("sm2p256v1" ); KeyGenerationParameters parameters = new ECKeyGenerationParameters(new ECDomainParameters(curve), new SecureRandom()); ECKeyPairGenerator generator = new ECKeyPairGenerator(); generator.Init(parameters); var keyPair = generator.GenerateKeyPair(); ECPrivateKeyParameters privateKeyParameters = (ECPrivateKeyParameters)keyPair.Private; privateKey = Base64.ToBase64String(privateKeyParameters.D.ToByteArrayUnsigned()); ECPublicKeyParameters publicKeyParameters = (ECPublicKeyParameters)keyPair.Public; publicKey = Base64.ToBase64String(publicKeyParameters.Q.GetEncoded()); }
SM2 公钥加密 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public static string Encrypt (string message, string key ){ X9ECParameters curve = ECNamedCurveTable.GetByName("sm2p256v1" ); ECPoint q = curve.Curve.DecodePoint(Base64.Decode(key)); ECDomainParameters domain = new ECDomainParameters(curve); ECPublicKeyParameters pubk = new ECPublicKeyParameters("EC" , q, domain); SM2Engine sm2Engine = new SM2Engine(); sm2Engine.Init(true , new ParametersWithRandom(pubk, new SecureRandom())); byte [] dataBytes = Encoding.UTF8.GetBytes(message); byte [] encryptedData = sm2Engine.ProcessBlock(dataBytes, 0 , dataBytes.Length); return Base64.ToBase64String(encryptedData); }
SM2 私钥解密 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public static string Decrypt (string message, string key ){ X9ECParameters curve = ECNamedCurveTable.GetByName("sm2p256v1" ); ECDomainParameters domain = new ECDomainParameters(curve); BigInteger d = new BigInteger(1 , Base64.Decode(key)); ECPrivateKeyParameters prik = new ECPrivateKeyParameters(d, domain); SM2Engine sm2Engine = new SM2Engine(); sm2Engine.Init(false , prik); byte [] encryptedData = Base64.Decode(message); byte [] decryptedData = sm2Engine.ProcessBlock(encryptedData, 0 , encryptedData.Length); return Encoding.UTF8.GetString(decryptedData); }
示例 1 2 3 4 5 6 7 8 9 string privateKey = "Ja4UIUJz7XRNDhIiuWXwL78qd1Pc7SC0/Z9LzyF4SL8=" ;string publicKey = "BGe1BZDFN+NhCQtc2qlVk8nUlXrIwcyjT3mMt7Xx3BkDNBGBQjFPV0+h3/cGUYXo2TFI1SShS7hWl9zi6SxUHvg=" ;string raw = "jacky" ;string e = Encrypt(raw, publicKey);Console.WriteLine($"加密结果:{e} " ); string d = Decrypt(e, privateKey);Console.WriteLine($"解密结果:{d} " );
运行结果:
这篇笔记整理自我自己的实践记录,如果做法有出入,或者你踩过别的坑,欢迎到 留言板 一起聊聊。