国密算法实战用BouncyCastle在C#中快速集成SM2/SM3/SM4当项目需要符合国密标准时大多数开发者面临的第一个难题是如何快速实现SM2非对称加密、SM3摘要算法和SM4对称加密。从头实现这些算法不仅耗时还可能引入安全隐患。本文将展示如何利用成熟的BouncyCastle密码库在C#项目中快速搭建国密算法支持。1. 环境准备与基础配置在开始之前我们需要准备好开发环境。对于C#项目来说BouncyCastle是最受欢迎的密码学库之一它提供了对国密算法的完整支持。首先通过NuGet安装BouncyCastleInstall-Package Portable.BouncyCastle -Version 1.9.0安装完成后我们需要定义一些基础参数和常量// SM4加密固定IV private const string SM4_IV zhjy-essa-ABCDEF; // SM2曲线参数使用GMNamedCurves确保国密标准 private static readonly X9ECParameters Sm2EcParams GMNamedCurves.GetByName(SM2P256V1); private static readonly ECDomainParameters Sm2DomainParams new ECDomainParameters( Sm2EcParams.Curve, Sm2EcParams.G, Sm2EcParams.N, Sm2EcParams.H);2. SM2密钥管理与加密解密SM2是基于椭圆曲线的非对称加密算法我们首先需要生成密钥对。2.1 生成SM2密钥对public static Dictionarystring, string GenerateSm2KeyPair() { var gen new ECKeyPairGenerator(); var keyGenParams new ECKeyGenerationParameters(Sm2DomainParams, new SecureRandom()); gen.Init(keyGenParams); var keyPair gen.GenerateKeyPair(); var privKey (ECPrivateKeyParameters)keyPair.Private; var pubKey (ECPublicKeyParameters)keyPair.Public; string priKeyHex privKey.D.ToString(16).ToLower(); string pubKeyHex Hex.ToHexString(pubKey.Q.GetEncoded(false)).ToLower(); return new Dictionarystring, string { { pubkey, pubKeyHex }, { prikey, priKeyHex } }; }2.2 SM2加密实现SM2加密需要注意密文格式问题国标推荐使用C1C3C2格式public static string Sm2Encrypt(string publicKeyHex, byte[] data, Sm2Mode mode Sm2Mode.C1C3C2) { try { byte[] pubBytes Hex.Decode(publicKeyHex); var pubPoint Sm2DomainParams.Curve.DecodePoint(pubBytes); var pubKeyParams new ECPublicKeyParameters(pubPoint, Sm2DomainParams); var engine new SM2Engine(new SM3Digest()); engine.Init(true, new ParametersWithRandom(pubKeyParams, new SecureRandom())); byte[] cipher engine.ProcessBlock(data, 0, data.Length); if (mode Sm2Mode.C1C2C3) cipher ChangeC1C3C2ToC1C2C3(cipher); return Convert.ToBase64String(cipher); } catch (Exception ex) { throw new Exception(SM2加密失败 ex.Message, ex); } }2.3 SM2解密实现解密时需要确保使用与加密时相同的密文格式public static byte[] Sm2Decrypt(string privateKeyHex, string cipherBase64, Sm2Mode mode Sm2Mode.C1C3C2) { try { byte[] cipher Convert.FromBase64String(cipherBase64); if (mode Sm2Mode.C1C2C3) cipher ChangeC1C2C3ToC1C3C2(cipher); BigInteger privD new BigInteger(privateKeyHex, 16); var privKeyParams new ECPrivateKeyParameters(privD, Sm2DomainParams); var engine new SM2Engine(new SM3Digest()); engine.Init(false, privKeyParams); return engine.ProcessBlock(cipher, 0, cipher.Length); } catch (Exception ex) { throw new Exception(SM2解密失败 ex.Message, ex); } }3. SM3摘要算法实现SM3是国密标准的哈希算法输出为256位(32字节)的摘要值public static string Sm3ComputeDigest(string data) { byte[] dataBytes Encoding.UTF8.GetBytes(data); return Sm3ComputeDigest(dataBytes); } public static string Sm3ComputeDigest(byte[] data) { SM3Digest sm3 new SM3Digest(); sm3.BlockUpdate(data, 0, data.Length); byte[] digest new byte[sm3.GetDigestSize()]; sm3.DoFinal(digest, 0); return Hex.ToHexString(digest).ToLower(); }4. SM4对称加密实战SM4是国密标准的对称加密算法密钥长度为128位。4.1 生成SM4密钥public static string Sm4GenerateKey() { byte[] key new byte[16]; using (var rng RandomNumberGenerator.Create()) rng.GetBytes(key); return Hex.ToHexString(key).ToLower(); }4.2 SM4加密实现public static string Sm4Encrypt(string sm4KeyHex, string plainText) { byte[] key Hex.Decode(sm4KeyHex); byte[] iv Encoding.UTF8.GetBytes(SM4_IV); byte[] plainBytes Encoding.UTF8.GetBytes(plainText); SM4Engine engine new SM4Engine(); CbcBlockCipher cbc new CbcBlockCipher(engine); PaddedBufferedBlockCipher cipher new PaddedBufferedBlockCipher(cbc, new Pkcs7Padding()); cipher.Init(true, new ParametersWithIV(new KeyParameter(key), iv)); byte[] cipherBytes cipher.DoFinal(plainBytes); return Convert.ToBase64String(cipherBytes); }4.3 SM4解密实现public static string Sm4Decrypt(string sm4KeyHex, string cipherBase64) { byte[] key Hex.Decode(sm4KeyHex); byte[] iv Encoding.UTF8.GetBytes(SM4_IV); byte[] cipherBytes Convert.FromBase64String(cipherBase64); SM4Engine engine new SM4Engine(); CbcBlockCipher cbc new CbcBlockCipher(engine); PaddedBufferedBlockCipher cipher new PaddedBufferedBlockCipher(cbc, new Pkcs7Padding()); cipher.Init(false, new ParametersWithIV(new KeyParameter(key), iv)); byte[] plainBytes cipher.DoFinal(cipherBytes); return Encoding.UTF8.GetString(plainBytes); }5. 实战技巧与常见问题在实际项目中集成国密算法时有几个关键点需要注意密钥管理SM2公私钥建议存储在安全的位置SM4密钥应该定期更换生产环境应该使用硬件安全模块(HSM)保护密钥性能优化SM2加密速度较慢适合加密小数据或加密SM4密钥大数据加密应该使用SM4可以考虑缓存SM2密钥对象避免重复解析跨平台兼容性不同系统对国密算法的实现可能有差异特别注意密文格式(C1C2C3 vs C1C3C2)测试时应该在不同平台验证加解密结果错误处理加解密操作应该放在try-catch块中记录详细的错误日志便于排查问题提供有意义的错误信息给调用方在实际项目中我们通常会将这些功能封装成工具类提供统一的接口给业务代码调用。这样可以降低使用复杂度提高代码的可维护性。