.NET C# 国密算法(SM算法)详细实现
1 SM2 - 椭圆曲线公钥密码算法
SM2 是基于椭圆曲线密码学 (ECC) 的公钥密码算法,功能类似于国际通用的 RSA 或 ECC,主要用于加密、签名和密钥交换。
-
特点
基于椭圆曲线的复杂数学问题(离散对数问题),安全性高。
密钥长度短:推荐使用 256 位椭圆曲线,比 RSA 2048 位更高效。
支持加密、数字签名和密钥协商。 -
主要应用场景
数据加密:点对点安全传输。
数字签名:身份认证、数据完整性校验。
密钥交换:安全通信中生成会话密钥。 -
技术细节
曲线参数采用推荐曲线sm2p256v1
,其定义与国际标准曲线secp256k1
类似。
椭圆曲线方程:y2=x3+ax+bmod py^2 = x^3 + ax + b \mod py2=x3+ax+bmodp, 其中 a=−3a = -3a=−3,bbb 和 ppp 是固定常数。 -
优点
性能优异:在同等安全等级下,计算效率高于 RSA。
国家标准:符合中国密码标准,适合中国市场使用。
using Hearth.Services.Security.Interfaces;
using Org.BouncyCastle.Asn1.GM;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;
using System.Text;
namespace Hearth.Services.Security
{
public class SM2Encryptor : IAsymmetricEncryptor
{
private byte[] _publicKey;
private byte[] _privateKey;
public byte[] Decrypt(byte[] data)
{
ArgumentNullException.ThrowIfNull(data);
ArgumentNullException.ThrowIfNull(_privateKey);
// 参数“1”必须,BigInteger 默认以有符号整数解析。如果私钥的最高位是 1,可能会被误解为负数,需要强制以无符号方式处理:
BigInteger d = new BigInteger(1, _privateKey);
X9ECParameters sm2Params = GMNamedCurves.GetByName("sm2p256v1");
ECDomainParameters domainParameters = new ECDomainParameters(sm2Params.Curve, sm2Params.G, sm2Params.N, sm2Params.H);
string dataHexStr = Hex.ToHexString(data);
string privateKeyHexStr = Hex.ToHexString(_privateKey);
AsymmetricKeyParameter keyParameter = new ECPrivateKeyParameters(d, domainParameters);
SM2Engine engine = new SM2Engine();
engine.Init(false, keyParameter);
byte[] decryptedData = engine.ProcessBlock(data, 0, data.Length);
return decryptedData;
}
public string Decrypt(string data)
{
ArgumentNullException.ThrowIfNull(data);
ArgumentNullException.ThrowIfNull(_privateKey);
byte[] encryptedData = Hex.Decode(data);
byte[] decryptedData = Decrypt(encryptedData);
return Encoding.UTF8.GetString(decryptedData);
}
public byte[] Encrypt(byte[] data)
{
ArgumentNullException.ThrowIfNull(data);
ArgumentNullException.ThrowIfNull(_publicKey);
X9ECParameters sm2Params = GMNamedCurves.GetByName("sm2p256v1");
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;
}
public string Encrypt(string data)
{
ArgumentNullException.ThrowIfNull(data);
ArgumentNullException.ThrowIfNull(_publicKey);
byte[] dataBytes = Encoding.UTF8.GetBytes(data);
byte[] encryptedData = Encrypt(dataBytes);
return Hex.ToHexString(encryptedData);
}
public string GetPrivateKey()
{
ArgumentNullException.ThrowIfNull(_privateKey);
return Hex.ToHexString(_privateKey);
}
public byte[] GetPrivateKeyBytes()
{
return _privateKey;
}
public string GetPublicKey()
{
ArgumentNullException.ThrowIfNull(_publicKey);
return Hex.ToHexString(_publicKey);
}
public byte[] GetPublicKeyBytes()
{
return _publicKey;
}
public void SetPrivateKey(string privateKey)
{
ArgumentNullException.ThrowIfNull(privateKey);
_privateKey = Hex.Decode(privateKey);
}
public void SetPrivateKey(byte[] privateKey)
{
_privateKey = privateKey;
}
public void SetPublicKey(string publicKey)
{
ArgumentNullException.ThrowIfNull(publicKey);
_publicKey = Hex.Decode(publicKey);
}
public void SetPublicKey(byte[] publicKey)
{
_publicKey = publicKey;
}
}
}
2 SM3 - 哈希算法
SM3 是一种杂凑算法,功能类似于国际标准的 SHA-256,但有独特的设计,增强了对碰撞攻击的抵抗能力。
- 特点
输出长度固定为 256 位。
抗碰撞性强:给定输入,几乎不可能找到两个具有相同哈希值的输入。
高效:计算速度快,适合在硬件或软件中实现。 - 主要应用场景
数字签名:结合 SM2 验证数据完整性。
消息认证:校验数据传输中的篡改。
数据指纹:生成文件或数据的唯一标识。 - 技术细节
基本结构基于 Merkle-Damgård 结构。
消息分组长度为 512 位,每次处理一个分组。
压缩函数包含 64 轮迭代,每轮使用不同的常量。 - 与 SHA-256 的区别
算法内部逻辑稍有不同,增强了安全性。
更适合与其他国密算法(如 SM2 和 SM4)结合使用。
using Hearth.Services.Security.Interfaces;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Utilities.Encoders;
using System.Text;
namespace Hearth.Services.Security
{
public class SM3Encryptor : IHashEncryptor
{
public byte[] Encrypt(byte[] data)
{
SM3Digest digest = new SM3Digest();
digest.BlockUpdate(data, 0, data.Length);
byte[] hash = new byte[digest.GetDigestSize()];
digest.DoFinal(hash, 0);
return hash;
}
public string Encrypt(string data)
{
byte[] dataBytes = Encoding.UTF8.GetBytes(data);
byte[] hashResult = Encrypt(dataBytes);
return Hex.ToHexString(hashResult);
}
}
}
3 SM4 - 分组对称加密算法
SM4 是一种对称加密算法,功能类似于 AES,用于数据加密和解密。
- 特点
块加密:以 128 位分组进行加密和解密。
密钥长度固定为 128 位。
采用 Feistel 结构,每轮执行 S-Box 替换、线性变换和密钥加混。 - 主要应用场景
无线网络安全:如 WLAN 认证和加密。
数据存储:文件加密和数据库保护。
通信安全:加密传输数据。 - 技术细节
总共有 32 轮加密。
使用 128 位的对称密钥。
提供 ECB、CBC、CFB、OFB 等常见的加密模式。 - 与 AES 的比较
相同分组长度(128 位)和密钥长度(128 位)。
在硬件实现上性能与 AES 相当,但设计上更适合中国密码标准环境。
3.1 CBC 模式(Cipher Block Chaining)
需要提供初始化向量(IV),它与密钥一起参与加密过程,对每个明文块加密前会先与前一个密文块进行异或操作,增强了加密安全性,避免了相同明文加密出相同密文的情况。
通过CipherUtilities.GetCipher(“SM4/CBC/PKCS7Padding”)获取对应的密码器实例,并使用ParametersWithIV结合密钥和 IV 进行初始化后执行加密操作。
using Hearth.Services.Security.Interfaces;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;
using System.Text;
namespace Hearth.Services.Security
{
public class SM4CBCEncryptor : IIVSymmetricEncryptor
{
private byte[] _key;
private byte[] _iv;
public byte[] Decrypt(byte[] data)
{
ArgumentNullException.ThrowIfNull(data);
ArgumentNullException.ThrowIfNull(_key);
ArgumentNullException.ThrowIfNull(_iv);
IBufferedCipher bufferedCipher = CipherUtilities.GetCipher("SM4/CBC/PKCS7Padding");
KeyParameter keyParameter = new KeyParameter(_key);
bufferedCipher.Init(false, new ParametersWithIV(keyParameter, _iv));
return bufferedCipher.DoFinal(data);
}
public string Decrypt(string data)
{
ArgumentNullException.ThrowIfNull(data);
ArgumentNullException.ThrowIfNull(_key);
ArgumentNullException.ThrowIfNull(_iv);
byte[] encryptedBytes = Hex.Decode(data);
byte[] decryptedBytes = Decrypt(encryptedBytes);
return Encoding.UTF8.GetString(decryptedBytes);
}
public byte[] Encrypt(byte[] data)
{
ArgumentNullException.ThrowIfNull(data);
ArgumentNullException.ThrowIfNull(_key);
ArgumentNullException.ThrowIfNull(_iv);
IBufferedCipher bufferedCipher = CipherUtilities.GetCipher("SM4/CBC/PKCS7Padding");
KeyParameter keyParameter = new KeyParameter(_key);
bufferedCipher.Init(true, new ParametersWithIV(keyParameter, _iv));
return bufferedCipher.DoFinal(data);
}
public string Encrypt(string data)
{
ArgumentNullException.ThrowIfNull(data);
ArgumentNullException.ThrowIfNull(_key);
ArgumentNullException.ThrowIfNull(_iv);
byte[] plainBytes = Encoding.UTF8.GetBytes(data);
byte[] encryptedBytes = Encrypt(plainBytes);
return Hex.ToHexString(encryptedBytes);
}
public string GetIV()
{
return Hex.ToHexString(_iv);
}
public byte[] GetIVBytes()
{
return _iv;
}
public string GetKey()
{
return Hex.ToHexString(_key);
}
public byte[] GetKeyBytes()
{
return _key;
}
public void SetIV(string iv)
{
_iv = Hex.Decode(iv);
}
public void SetIV(byte[] iv)
{
_iv = iv;
}
public void SetKey(string key)
{
_key = Hex.Decode(key);
}
public void SetKey(byte[] key)
{
_key = key;
}
}
}
3.2 ECB 模式(Electronic Codebook)
是最简单的模式,每个明文块独立加密,相同的明文块会加密出相同的密文块,安全性相对较低,常用于一些对数据完整性要求不高的场景或者结合其他技术使用。
直接使用CipherUtilities.GetCipher(“SM4/ECB/PKCS7Padding”)获取密码器,用密钥初始化后进行加密。
using Hearth.Services.Security.Interfaces;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;
using System.Text;
namespace Hearth.Services.Security
{
public class SM4ECBEncryptor : ISymmetricEncryptor
{
private byte[] _key;
public byte[] Decrypt(byte[] data)
{
ArgumentNullException.ThrowIfNull(data);
ArgumentNullException.ThrowIfNull(_key);
IBufferedCipher bufferedCipher = CipherUtilities.GetCipher("SM4/ECB/PKCS7Padding");
KeyParameter keyParameter = new KeyParameter(_key);
bufferedCipher.Init(false, keyParameter);
return bufferedCipher.DoFinal(data);
}
public string Decrypt(string data)
{
ArgumentNullException.ThrowIfNull(data);
ArgumentNullException.ThrowIfNull(_key);
byte[] encryptedBytes = Hex.Decode(data);
byte[] decryptedBytes = Decrypt(encryptedBytes);
return Encoding.UTF8.GetString(decryptedBytes);
}
public byte[] Encrypt(byte[] data)
{
ArgumentNullException.ThrowIfNull(data);
ArgumentNullException.ThrowIfNull(_key);
IBufferedCipher bufferedCipher = CipherUtilities.GetCipher("SM4/ECB/PKCS7Padding");
KeyParameter keyParameter = new KeyParameter(_key);
bufferedCipher.Init(true, keyParameter);
return bufferedCipher.DoFinal(data);
}
public string Encrypt(string data)
{
ArgumentNullException.ThrowIfNull(data);
ArgumentNullException.ThrowIfNull(_key);
byte[] plainBytes = Encoding.UTF8.GetBytes(data);
byte[] encryptedBytes = Encrypt(plainBytes);
return Hex.ToHexString(encryptedBytes);
}
public string GetKey()
{
return Hex.ToHexString(_key);
}
public byte[] GetKeyBytes()
{
return _key;
}
public void SetKey(string key)
{
_key = Hex.Decode(key);
}
public void SetKey(byte[] key)
{
_key = key;
}
}
}
3.3 CFB 模式(Cipher Feedback)
也需要 IV,它将加密后的部分结果反馈到加密过程中,以实现类似流密码的效果,加密时不需要对明文进行分组填充等操作,加密单位可以更小,比如按位或者字节等。
使用CfbBlockCipher结合SM4Engine构建BufferedBlockCipher,再用密钥和 IV 初始化后加密。
using Hearth.Services.Security.Interfaces;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Utilities.Encoders;
using System.Text;
namespace Hearth.Services.Security
{
public class SM4CFBEncryptor : IIVSymmetricEncryptor
{
private byte[] _key;
private byte[] _iv;
public byte[] Decrypt(byte[] data)
{
ArgumentNullException.ThrowIfNull(data);
ArgumentNullException.ThrowIfNull(_key);
ArgumentNullException.ThrowIfNull(_iv);
IBlockCipher engine = new SM4Engine();
CfbBlockCipher blockCipher = new CfbBlockCipher(engine, 128);
BufferedBlockCipher bufferedBlockCipher = new BufferedBlockCipher(blockCipher);
bufferedBlockCipher.Init(false, new ParametersWithIV(new KeyParameter(_key), _iv));
return bufferedBlockCipher.DoFinal(data);
}
public string Decrypt(string data)
{
ArgumentNullException.ThrowIfNull(data);
ArgumentNullException.ThrowIfNull(_key);
ArgumentNullException.ThrowIfNull(_iv);
byte[] encryptedBytes = Hex.Decode(data);
byte[] decryptedBytes = Decrypt(encryptedBytes);
return Encoding.UTF8.GetString(decryptedBytes);
}
public byte[] Encrypt(byte[] data)
{
ArgumentNullException.ThrowIfNull(data);
ArgumentNullException.ThrowIfNull(_key);
ArgumentNullException.ThrowIfNull(_iv);
IBlockCipher engine = new SM4Engine();
CfbBlockCipher blockCipher = new CfbBlockCipher(engine, 128);
BufferedBlockCipher bufferedBlockCipher = new BufferedBlockCipher(blockCipher);
bufferedBlockCipher.Init(true, new ParametersWithIV(new KeyParameter(_key), _iv));
return bufferedBlockCipher.DoFinal(data);
}
public string Encrypt(string data)
{
ArgumentNullException.ThrowIfNull(data);
ArgumentNullException.ThrowIfNull(_key);
ArgumentNullException.ThrowIfNull(_iv);
byte[] plainBytes = Encoding.UTF8.GetBytes(data);
byte[] encryptedBytes = Encrypt(plainBytes);
return Hex.ToHexString(encryptedBytes);
}
public string GetIV()
{
return Hex.ToHexString(_iv);
}
public byte[] GetIVBytes()
{
return _iv;
}
public string GetKey()
{
return Hex.ToHexString(_key);
}
public byte[] GetKeyBytes()
{
return _key;
}
public void SetIV(string iv)
{
_iv = Hex.Decode(iv);
}
public void SetIV(byte[] iv)
{
_iv = iv;
}
public void SetKey(string key)
{
_key = Hex.Decode(key);
}
public void SetKey(byte[] key)
{
_key = key;
}
}
}
3.4 OFB 模式(Output Feedback)
同样依赖 IV,它生成一个密钥流,将明文与密钥流进行异或操作来加密,加密过程中密钥流的生成与明文无关,只要密钥和 IV 相同,生成的密钥流就相同,在某些场景下使用较为方便。
利用OfbBlockCipher结合SM4Engine构建BufferedBlockCipher,使用密钥和 IV 初始化来完成加密。
using Hearth.Services.Security.Interfaces;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Utilities.Encoders;
using System.Text;
namespace Hearth.Services.Security
{
public class SM4OFBEncryptor : IIVSymmetricEncryptor
{
private byte[] _key;
private byte[] _iv;
public byte[] Decrypt(byte[] data)
{
ArgumentNullException.ThrowIfNull(data);
ArgumentNullException.ThrowIfNull(_key);
ArgumentNullException.ThrowIfNull(_iv);
IBlockCipher engine = new SM4Engine();
OfbBlockCipher blockCipher = new OfbBlockCipher(engine, 128);
BufferedBlockCipher bufferedBlockCipher = new BufferedBlockCipher(blockCipher);
bufferedBlockCipher.Init(false, new ParametersWithIV(new KeyParameter(_key), _iv));
return bufferedBlockCipher.DoFinal(data);
}
public string Decrypt(string data)
{
ArgumentNullException.ThrowIfNull(data);
ArgumentNullException.ThrowIfNull(_key);
ArgumentNullException.ThrowIfNull(_iv);
byte[] encryptedBytes = Hex.Decode(data);
byte[] decryptedBytes = Decrypt(encryptedBytes);
return Encoding.UTF8.GetString(decryptedBytes);
}
public byte[] Encrypt(byte[] data)
{
ArgumentNullException.ThrowIfNull(data);
ArgumentNullException.ThrowIfNull(_key);
ArgumentNullException.ThrowIfNull(_iv);
IBlockCipher engine = new SM4Engine();
OfbBlockCipher blockCipher = new OfbBlockCipher(engine, 128);
BufferedBlockCipher bufferedBlockCipher = new BufferedBlockCipher(blockCipher);
bufferedBlockCipher.Init(true, new ParametersWithIV(new KeyParameter(_key), _iv));
return bufferedBlockCipher.DoFinal(data);
}
public string Encrypt(string data)
{
ArgumentNullException.ThrowIfNull(data);
ArgumentNullException.ThrowIfNull(_key);
ArgumentNullException.ThrowIfNull(_iv);
byte[] plainBytes = Encoding.UTF8.GetBytes(data);
byte[] encryptedBytes = Encrypt(plainBytes);
return Hex.ToHexString(encryptedBytes);
}
public string GetIV()
{
return Hex.ToHexString(_iv);
}
public byte[] GetIVBytes()
{
return _iv;
}
public string GetKey()
{
return Hex.ToHexString(_key);
}
public byte[] GetKeyBytes()
{
return _key;
}
public void SetIV(string iv)
{
_iv = Hex.Decode(iv);
}
public void SetIV(byte[] iv)
{
_iv = iv;
}
public void SetKey(string key)
{
_key = Hex.Decode(key);
}
public void SetKey(byte[] key)
{
_key = key;
}
}
}
4 附录
4.1 环境
- 语言框架:C# + .NET 8
- 依赖库:BouncyCastle.Cryptography 版本:2.4.0
4.2 接口列表
namespace Hearth.Services.Security.Interfaces
{
/// <summary>
/// 可解密接口
/// </summary>
public interface IDecryptable
{
/// <summary>
/// 解密数据
/// </summary>
/// <param name="data">密文数据</param>
/// <returns>明文数据</returns>
byte[] Decrypt(byte[] data);
/// <summary>
/// 解密数据
/// </summary>
/// <param name="data">密文</param>
/// <returns>明文</returns>
string Decrypt(string data);
}
}
namespace Hearth.Services.Security.Interfaces
{
/// <summary>
/// 可加密的接口
/// </summary>
public interface IEncryptable
{
/// <summary>
/// 加密数据
/// </summary>
/// <param name="data">明文数据</param>
/// <returns>密文数据</returns>
byte[] Encrypt(byte[] data);
/// <summary>
/// 加密数据
/// </summary>
/// <param name="data">明文</param>
/// <returns>密文</returns>
string Encrypt(string data);
}
}
namespace Hearth.Services.Security.Interfaces
{
/// <summary>
/// 哈希加密器接口
/// </summary>
public interface IHashEncryptor : IEncryptable
{
}
}
namespace Hearth.Services.Security.Interfaces
{
/// <summary>
/// 对称加密器接口
/// </summary>
public interface ISymmetricEncryptor : IEncryptable, IDecryptable
{
/// <summary>
/// 设置密钥
/// </summary>
/// <param name="key">秘钥</param>
void SetKey(string key);
/// <summary>
/// 设置密钥
/// </summary>
/// <param name="key">秘钥</param>
void SetKey(byte[] key);
/// <summary>
/// 获取密钥
/// </summary>
string GetKey();
/// <summary>
/// 获取密钥字节数组
/// </summary>
byte[] GetKeyBytes();
}
}
namespace Hearth.Services.Security.Interfaces
{
/// <summary>
/// 初始化向量对称加密器接口
/// </summary>
public interface IIVSymmetricEncryptor : ISymmetricEncryptor
{
/// <summary>
/// 设置初始化向量
/// </summary>
void SetIV(string key);
/// <summary>
/// 设置初始化向量
/// </summary>
/// <param name="key"></param>
void SetIV(byte[] key);
/// <summary>
/// 获取初始化向量
/// </summary>
/// <returns></returns>
string GetIV();
/// <summary>
/// 获取初始化向量
/// </summary>
/// <returns></returns>
byte[] GetIVBytes();
}
}
namespace Hearth.Services.Security.Interfaces
{
/// <summary>
/// 非对称加密器接口
/// </summary>
public interface IAsymmetricEncryptor : IEncryptable, IDecryptable
{
/// <summary>
/// 设置公钥
/// </summary>
void SetPublicKey(string publicKey);
/// <summary>
/// 设置公钥
/// </summary>
void SetPublicKey(byte[] publicKey);
/// <summary>
/// 设置私钥
/// </summary>
void SetPrivateKey(string privateKey);
/// <summary>
/// 设置私钥
/// </summary>
void SetPrivateKey(byte[] privateKey);
/// <summary>
/// 获取公钥
/// </summary>
string GetPublicKey();
/// <summary>
/// 获取公钥
/// </summary>
string GetPrivateKey();
/// <summary>
/// 获取公钥字节数组
/// </summary>
byte[] GetPublicKeyBytes();
/// <summary>
/// 获取私钥字节数组
/// </summary>
byte[] GetPrivateKeyBytes();
}
}
4.3 测试用例
using Hearth.Services.Security.Interfaces;
using Org.BouncyCastle.Asn1.GM;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;
namespace Hearth.Services.Security.Tests
{
public class SM2EncryptorTests
{
[Fact]
public void EncryptDecrypt_PlainText_ReturnEqualOriginalPlainText()
{
// Arrange
// Step 1: 获取 SM2 曲线参数
X9ECParameters sm2Params = GMNamedCurves.GetByName("sm2p256v1");
ECDomainParameters domainParams = new ECDomainParameters(sm2Params.Curve, sm2Params.G, sm2Params.N, sm2Params.H);
// Step 2: 初始化密钥生成器
ECKeyPairGenerator keyGen = new ECKeyPairGenerator();
SecureRandom random = new SecureRandom();
ECKeyGenerationParameters keyGenParam = new ECKeyGenerationParameters(domainParams, random);
keyGen.Init(keyGenParam);
// Step 3: 生成密钥对
AsymmetricCipherKeyPair keyPair = keyGen.GenerateKeyPair();
ECPrivateKeyParameters privateKeyParams = (ECPrivateKeyParameters)keyPair.Private;
ECPublicKeyParameters publicKeyParams = (ECPublicKeyParameters)keyPair.Public;
// Step 4: 将私钥和公钥转为16进制字符串
string privateKeyHex = privateKeyParams.D.ToString(16);
string publicKeyHex = Hex.ToHexString(publicKeyParams.Q.GetEncoded()); // 非压缩格式
// Act
// Step 5: 使用公钥加密字符串
string plaintext = "Hello, SM2!";
IAsymmetricEncryptor encryptor = new SM2Encryptor();
encryptor.SetPublicKey(publicKeyHex);
var ciphertext = encryptor.Encrypt(plaintext);
// Step 6: 使用私钥解密数据
encryptor.SetPrivateKey(privateKeyHex);
string ciphertextDecrypted = encryptor.Decrypt(ciphertext);
// Assert
Assert.Equal(plaintext, ciphertextDecrypted);
}
}
}
using Hearth.Services.Security.Interfaces;
using System.Text;
namespace Hearth.Services.Security.Tests
{
public class SM3EncryptorTests
{
[Fact]
public void Encrypt_PlainText_ShouldReturnCipherText()
{
// Arrange
IHashEncryptor encryptor = new SM3Encryptor();
string plainText = "Hello, world!";
byte[] plainBytes = Encoding.UTF8.GetBytes(plainText);
// Act
string encryptedString = encryptor.Encrypt(plainText);
byte[] encryptedBytes = encryptor.Encrypt(plainBytes);
string base64String = Convert.ToBase64String(encryptedBytes);
// Assert
Assert.NotNull(encryptedString);
}
}
}
using Hearth.Services.Security.Interfaces;
using System.Security.Cryptography;
namespace Hearth.Services.Security.Tests
{
public class SM4CBCEncryptorTests
{
[Fact]
public void EncryptDecrypt_PlainText_ReturnOriginalPlainText()
{
// Arrange
byte[] key = new byte[16];
byte[] iv = new byte[16];
using (var generator = RandomNumberGenerator.Create())
{
generator.GetBytes(key);
generator.GetBytes(iv);
}
IIVSymmetricEncryptor encryptor = new SM4CBCEncryptor();
encryptor.SetKey(key);
encryptor.SetIV(iv);
string plainText = "Hello, world!";
// Act
string cipherText = encryptor.Encrypt(plainText);
string decryptedText = encryptor.Decrypt(cipherText);
// Assert
Assert.Equal(plainText, decryptedText);
}
[Fact]
public void MultipleEncrypt_EqualPlainText_ReturnDifferentCipherText()
{
// Arrange
byte[] key = new byte[16];
byte[] iv1 = new byte[16];
byte[] iv2 = new byte[16];
using (var generator = RandomNumberGenerator.Create())
{
generator.GetBytes(key);
generator.GetBytes(iv1);
generator.GetBytes(iv2);
}
IIVSymmetricEncryptor encryptor1 = new SM4CFBEncryptor();
encryptor1.SetKey(key);
encryptor1.SetIV(iv1);
IIVSymmetricEncryptor encryptor2 = new SM4CFBEncryptor();
encryptor2.SetKey(key);
encryptor2.SetIV(iv2);
string plainText = "Hello, world!";
// Act
string cipherText1 = encryptor1.Encrypt(plainText);
string cipherText2 = encryptor2.Encrypt(plainText);
// Assert
Assert.NotEqual(cipherText1, cipherText2);
}
}
}
using Hearth.Services.Security.Interfaces;
using System.Security.Cryptography;
namespace Hearth.Services.Security.Tests
{
public class SM4CFBEncryptorTests
{
[Fact]
public void EncryptDecrypt_PlainText_ReturnOriginalPlainText()
{
// Arrange
byte[] key = new byte[16];
byte[] iv = new byte[16];
using (var generator = RandomNumberGenerator.Create())
{
generator.GetBytes(key);
generator.GetBytes(iv);
}
IIVSymmetricEncryptor encryptor = new SM4CFBEncryptor();
encryptor.SetKey(key);
encryptor.SetIV(iv);
string plainText = "Hello, world!";
// Act
string cipherText = encryptor.Encrypt(plainText);
string decryptedText = encryptor.Decrypt(cipherText);
// Assert
Assert.Equal(plainText, decryptedText);
}
[Fact]
public void MultipleEncrypt_EqualPlainText_ReturnDifferentCipherText()
{
// Arrange
byte[] key = new byte[16];
byte[] iv1 = new byte[16];
byte[] iv2 = new byte[16];
using (var generator = RandomNumberGenerator.Create())
{
generator.GetBytes(key);
generator.GetBytes(iv1);
generator.GetBytes(iv2);
}
IIVSymmetricEncryptor encryptor1 = new SM4CFBEncryptor();
encryptor1.SetKey(key);
encryptor1.SetIV(iv1);
IIVSymmetricEncryptor encryptor2 = new SM4CFBEncryptor();
encryptor2.SetKey(key);
encryptor2.SetIV(iv2);
string plainText = "Hello, world!";
// Act
string cipherText1 = encryptor1.Encrypt(plainText);
string cipherText2 = encryptor2.Encrypt(plainText);
// Assert
Assert.NotEqual(cipherText1, cipherText2);
}
}
}
using Hearth.Services.Security.Interfaces;
using System.Security.Cryptography;
namespace Hearth.Services.Security.Tests
{
public class SM4ECBEncryptorTests
{
[Fact]
public void EncryptDecrypt_PlainText_ReturnOriginalPlainText()
{
// Arrange
byte[] key = new byte[16];
using (var generator = RandomNumberGenerator.Create())
{
generator.GetBytes(key);
}
ISymmetricEncryptor encryptor = new SM4ECBEncryptor();
encryptor.SetKey(key);
string plainText = "Hello, world!";
// Act
string cipherText = encryptor.Encrypt(plainText);
string decryptedText = encryptor.Decrypt(cipherText);
// Assert
Assert.Equal(plainText, decryptedText);
}
[Fact]
public void MultipleEncrypt_EqualPlainText_ReturnECipherText()
{
// Arrange
byte[] key = new byte[16];
using (var generator = RandomNumberGenerator.Create())
{
generator.GetBytes(key);
}
ISymmetricEncryptor encryptor1 = new SM4ECBEncryptor();
encryptor1.SetKey(key);
ISymmetricEncryptor encryptor2 = new SM4ECBEncryptor();
encryptor2.SetKey(key);
string plainText = "Hello, world!";
// Act
string cipherText1 = encryptor1.Encrypt(plainText);
string cipherText2 = encryptor2.Encrypt(plainText);
// Assert
Assert.Equal(cipherText1, cipherText2);
}
}
}
using Hearth.Services.Security.Interfaces;
using System.Security.Cryptography;
namespace Hearth.Services.Security.Tests
{
public class SM4OFBEncryptorTests
{
[Fact]
public void EncryptDecrypt_PlainText_ReturnOriginalPlainText()
{
// Arrange
byte[] key = new byte[16];
byte[] iv = new byte[16];
using (var generator = RandomNumberGenerator.Create())
{
generator.GetBytes(key);
generator.GetBytes(iv);
}
IIVSymmetricEncryptor encryptor = new SM4OFBEncryptor();
encryptor.SetKey(key);
encryptor.SetIV(iv);
string plainText = "Hello, world!";
// Act
string cipherText = encryptor.Encrypt(plainText);
string decryptedText = encryptor.Decrypt(cipherText);
// Assert
Assert.Equal(plainText, decryptedText);
}
[Fact]
public void MultipleEncrypt_ShouldReturnDifferentCipherText()
{
// Arrange
byte[] key = new byte[16];
byte[] iv1 = new byte[16];
byte[] iv2 = new byte[16];
using (var generator = RandomNumberGenerator.Create())
{
generator.GetBytes(key);
generator.GetBytes(iv1);
generator.GetBytes(iv2);
}
IIVSymmetricEncryptor encryptor1 = new SM4OFBEncryptor();
encryptor1.SetKey(key);
encryptor1.SetIV(iv1);
IIVSymmetricEncryptor encryptor2 = new SM4OFBEncryptor();
encryptor2.SetKey(key);
encryptor2.SetIV(iv2);
string plainText = "Hello, world!";
// Act
string cipherText1 = encryptor1.Encrypt(plainText);
string cipherText2 = encryptor2.Encrypt(plainText);
// Assert
Assert.NotEqual(cipherText1, cipherText2);
}
}
}