.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);// AssertAssert.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(){// ArrangeIHashEncryptor encryptor = new SM3Encryptor();string plainText = "Hello, world!";byte[] plainBytes = Encoding.UTF8.GetBytes(plainText);// Actstring encryptedString = encryptor.Encrypt(plainText);byte[] encryptedBytes = encryptor.Encrypt(plainBytes);string base64String = Convert.ToBase64String(encryptedBytes);// AssertAssert.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(){// Arrangebyte[] 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!";// Actstring cipherText = encryptor.Encrypt(plainText);string decryptedText = encryptor.Decrypt(cipherText);// AssertAssert.Equal(plainText, decryptedText);}[Fact]public void MultipleEncrypt_EqualPlainText_ReturnDifferentCipherText(){// Arrangebyte[] 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!";// Actstring cipherText1 = encryptor1.Encrypt(plainText);string cipherText2 = encryptor2.Encrypt(plainText);// AssertAssert.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(){// Arrangebyte[] 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!";// Actstring cipherText = encryptor.Encrypt(plainText);string decryptedText = encryptor.Decrypt(cipherText);// AssertAssert.Equal(plainText, decryptedText);}[Fact]public void MultipleEncrypt_EqualPlainText_ReturnDifferentCipherText(){// Arrangebyte[] 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!";// Actstring cipherText1 = encryptor1.Encrypt(plainText);string cipherText2 = encryptor2.Encrypt(plainText);// AssertAssert.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(){// Arrangebyte[] key = new byte[16];using (var generator = RandomNumberGenerator.Create()){generator.GetBytes(key);}ISymmetricEncryptor encryptor = new SM4ECBEncryptor();encryptor.SetKey(key);string plainText = "Hello, world!";// Actstring cipherText = encryptor.Encrypt(plainText);string decryptedText = encryptor.Decrypt(cipherText);// AssertAssert.Equal(plainText, decryptedText);}[Fact]public void MultipleEncrypt_EqualPlainText_ReturnECipherText(){// Arrangebyte[] 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!";// Actstring cipherText1 = encryptor1.Encrypt(plainText);string cipherText2 = encryptor2.Encrypt(plainText);// AssertAssert.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(){// Arrangebyte[] 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!";// Actstring cipherText = encryptor.Encrypt(plainText);string decryptedText = encryptor.Decrypt(cipherText);// AssertAssert.Equal(plainText, decryptedText);}[Fact]public void MultipleEncrypt_ShouldReturnDifferentCipherText(){// Arrangebyte[] 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!";// Actstring cipherText1 = encryptor1.Encrypt(plainText);string cipherText2 = encryptor2.Encrypt(plainText);// AssertAssert.NotEqual(cipherText1, cipherText2);}}
}