使用 BouncyCastle 库在 Unity 中实现 SM2 国密算法
SM2 是中国自主研发的椭圆曲线公钥密码算法,广泛应用于电子认证、数据加密等领域。 导入BouncyCastle库 1. 环境配置 从nuget包解压引入 BouncyCastle.Crypto.dll 至 Unity 项目的 Plugin 目录 添加必要的命名空间引用:using Org.BouncyCastle.Asn1.GM; using Org.BouncyCa
·
SM2 是中国自主研发的椭圆曲线公钥密码算法,广泛应用于电子认证、数据加密等领域。
以下代码已上传到仓库:https://gitcode.com/DSOE1024/UnitySM2Sample
导入BouncyCastle库
1. 环境配置
- 从nuget包解压引入
BouncyCastle.Crypto.dll
至 Unity 项目的 Plugin 目录
- 添加必要的命名空间引用:
using Org.BouncyCastle.Asn1.GM; using Org.BouncyCastle.Asn1.X9; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Generators; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities.Encoders; using System.Text;
2. 密钥对生成
通过椭圆曲线参数生成 SM2 密钥对:
X9ECParameters sm2Params = ECNamedCurveTable.GetByName("sm2p256v1");
// 初始化密钥生成器
ECKeyPairGenerator generator = new ECKeyPairGenerator();
generator.Init(new ECKeyGenerationParameters(
new ECDomainParameters(sm2Params.Curve, sm2Params.G, sm2Params.N),
new SecureRandom()
));
// 生成并提取密钥
AsymmetricCipherKeyPair keyPair = generator.GenerateKeyPair();
ECPrivateKeyParameters privateKey = (ECPrivateKeyParameters)keyPair.Private;
ECPublicKeyParameters publicKey = (ECPublicKeyParameters)keyPair.Public;
3. 加密
使用公钥加密数据:
public byte[] Encrypt(byte[] data, byte[] publicKey)
{
// 加载公钥并初始化加密引擎
ECPublicKeyParameters pubKeyParams = new ECPublicKeyParameters(
sm2Params.Curve.DecodePoint(publicKey),
new ECDomainParameters(sm2Params.Curve)
);
SM2Engine engine = new SM2Engine();
engine.Init(true, new ParametersWithRandom(pubKeyParams, new SecureRandom()));
return engine.ProcessBlock(data, 0, data.Length);
}
4. 解密
使用私钥解密数据:
public byte[] Decrypt(byte[] cipherData, byte[] privateKey)
{
// 加载私钥参数
ECPrivateKeyParameters privKeyParams = new ECPrivateKeyParameters(
new BigInteger(1, privateKey),
new ECDomainParameters(sm2Params.Curve)
);
SM2Engine engine = new SM2Engine();
engine.Init(false, privKeyParams);
return engine.ProcessBlock(cipherData, 0, cipherData.Length);
}
完整示例代码
using Org.BouncyCastle.Asn1.GM;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;
using System.Text;
using UnityEngine;
/// <summary>
/// SM2 加密解密示例
/// </summary>
public class SM2Sample : MonoBehaviour
{
private byte[] pubKey;
private byte[] privKey;
private string content = "加密的内容";
private void Start()
{
GenerateKeyPair(out string priKeyStr, out string pubKeyStr);
privKey = Hex.Decode(priKeyStr);
pubKey = Hex.Decode(pubKeyStr);
var str = EncryptString(content);
Debug.Log($"加密后 { str } ");
Debug.Log($"解密后 { DecryptString(str) }");
}
/// <summary>
/// 生成密钥对
/// </summary>
/// <param name="privateKeyHex"></param>
/// <param name="publicKeyHex"></param>
public static void GenerateKeyPair(out string privateKeyHex, out string publicKeyHex)
{
// 获取 SM2 椭圆曲线参数
X9ECParameters sm2Params = ECNamedCurveTable.GetByName("sm2p256v1");
ECDomainParameters domainParams = new ECDomainParameters(
sm2Params.Curve,
sm2Params.G,
sm2Params.N,
sm2Params.H
);
// 初始化密钥对生成器
ECKeyPairGenerator generator = new ECKeyPairGenerator();
ECKeyGenerationParameters keyGenParams = new ECKeyGenerationParameters(
domainParams,
new SecureRandom() // 使用安全的随机数生成器
);
generator.Init(keyGenParams);
// 生成密钥对
AsymmetricCipherKeyPair keyPair = generator.GenerateKeyPair();
// 提取私钥 (BigInteger D)
ECPrivateKeyParameters privateKey = (ECPrivateKeyParameters)keyPair.Private;
byte[] privateKeyBytes = privateKey.D.ToByteArrayUnsigned(); // 转换为无符号字节数组
privateKeyHex = Hex.ToHexString(privateKeyBytes);
// 提取公钥 (ECPoint Q)
ECPublicKeyParameters publicKey = (ECPublicKeyParameters)keyPair.Public;
byte[] publicKeyBytes = publicKey.Q.GetEncoded(false); // 非压缩格式(含04前缀)
publicKeyHex = Hex.ToHexString(publicKeyBytes);
}
/// <summary>
/// 解密
/// </summary>
/// <param name="data"></param>
/// <param name="privateKey"></param>
/// <returns></returns>
public byte[] Decrypt(byte[] data, byte[] privateKey)
{
BigInteger d = new BigInteger(1, privateKey);
X9ECParameters spar = ECNamedCurveTable.GetByName("sm2p256v1");
ECDomainParameters ecdp = new ECDomainParameters(spar.Curve, spar.G, spar.N, spar.H);
// 创建私钥参数
ECPrivateKeyParameters keyParameter = new ECPrivateKeyParameters(d, ecdp);
SM2Engine engine = new SM2Engine();
engine.Init(false, keyParameter);
byte[] decryptedData = engine.ProcessBlock(data, 0, data.Length);
return decryptedData;
}
/// <summary>
/// 解密
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public string DecryptString(string data)
{
byte[] encryptedData = Hex.Decode(data);
byte[] decryptedData = Decrypt(encryptedData, privKey);
return Encoding.UTF8.GetString(decryptedData);
}
/// <summary>
/// 加密
/// </summary>
/// <param name="data"></param>
/// <param name="publicKey"></param>
/// <returns></returns>
public byte[] Encrypt(byte[] data, byte[] publicKey)
{
X9ECParameters sm2Params = GMNamedCurves.GetByName("sm2p256v1");
Org.BouncyCastle.Math.EC.ECPoint q = sm2Params.Curve.DecodePoint(publicKey);
ECDomainParameters domainParameters = new ECDomainParameters(sm2Params.Curve, sm2Params.G, sm2Params.N, sm2Params.H);
AsymmetricKeyParameter keyParameter = new ECPublicKeyParameters(q, domainParameters);
SM2Engine engine = new SM2Engine();
engine.Init(true, new ParametersWithRandom(keyParameter, new SecureRandom()));
byte[] encryptedData = engine.ProcessBlock(data, 0, data.Length);
return encryptedData;
}
/// <summary>
/// 加密
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public string EncryptString(string data)
{
byte[] dataBytes = Encoding.UTF8.GetBytes(data);
byte[] encryptedData = Encrypt(dataBytes, pubKey);
return Hex.ToHexString(encryptedData);
}
}
注意事项
-
密钥格式
公钥需包含04
前缀表示非压缩格式,私钥为无符号大整数字节数组。 -
性能优化
SM2Engine
加解密过程较耗时,建议避免在主线程处理大数据。 -
数据兼容性
与其他系统交互时需确认椭圆曲线参数是否一致(sm2p256v1)。 -
错误处理
添加异常捕获处理密钥格式错误、解密失败等情况。
更多推荐
所有评论(0)