196 lines
6.7 KiB
C#
196 lines
6.7 KiB
C#
using Org.BouncyCastle.Crypto.Digests;
|
||
using Org.BouncyCastle.Crypto.Engines;
|
||
using Org.BouncyCastle.Crypto.Modes;
|
||
using Org.BouncyCastle.Crypto.Paddings;
|
||
using Org.BouncyCastle.Crypto.Parameters;
|
||
using Org.BouncyCastle.Math;
|
||
using Org.BouncyCastle.Security;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Security.Cryptography;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace Infrastructure.Helpers
|
||
{
|
||
public class SM4CryptoHelper
|
||
{
|
||
const int SM4_KEY_SIZE = 128 / 8; // 16 bytes
|
||
const int BLOCK_SIZE = 16; // SM4 block size is 16 bytes
|
||
|
||
#region 随机密钥
|
||
/// <summary>
|
||
/// sm4 随机密钥
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public static byte[] GenerateSM4Key()
|
||
{
|
||
using (var rng = RandomNumberGenerator.Create())
|
||
{
|
||
byte[] key = new byte[SM4_KEY_SIZE];
|
||
rng.GetBytes(key);
|
||
return key;
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region CBC模式,PKCS7填充
|
||
// 生成随机IV
|
||
public static byte[] GenerateIV()
|
||
{
|
||
using (var rng = RandomNumberGenerator.Create())
|
||
{
|
||
byte[] iv = new byte[BLOCK_SIZE];
|
||
rng.GetBytes(iv);
|
||
return iv;
|
||
}
|
||
}
|
||
|
||
// SM4加密 (CBC模式,PKCS7填充)
|
||
public static byte[] SM4Encrypt(byte[] key, byte[] iv, byte[] plaintext)
|
||
{
|
||
// 创建加密器
|
||
var engine = new SM4Engine();
|
||
var blockCipher = new CbcBlockCipher(engine);
|
||
var cipher = new PaddedBufferedBlockCipher(blockCipher, new Pkcs7Padding());
|
||
var keyParam = new KeyParameter(key);
|
||
var keyParamWithIv = new ParametersWithIV(keyParam, iv);
|
||
|
||
// 初始化加密器
|
||
cipher.Init(true, keyParamWithIv);
|
||
|
||
// 处理数据
|
||
byte[] output = new byte[cipher.GetOutputSize(plaintext.Length)];
|
||
int len = cipher.ProcessBytes(plaintext, 0, plaintext.Length, output, 0);
|
||
len += cipher.DoFinal(output, len);
|
||
|
||
// 返回正确长度的密文
|
||
if (len < output.Length)
|
||
{
|
||
byte[] result = new byte[len];
|
||
Array.Copy(output, 0, result, 0, len);
|
||
return result;
|
||
}
|
||
|
||
return output;
|
||
}
|
||
|
||
// SM4解密 (CBC模式,PKCS7填充)
|
||
public static byte[] SM4Decrypt(byte[] key, byte[] iv, byte[] ciphertext)
|
||
{
|
||
// 创建解密器
|
||
var engine = new SM4Engine();
|
||
var blockCipher = new CbcBlockCipher(engine);
|
||
var cipher = new PaddedBufferedBlockCipher(blockCipher, new Pkcs7Padding());
|
||
var keyParam = new KeyParameter(key);
|
||
var keyParamWithIv = new ParametersWithIV(keyParam, iv);
|
||
|
||
// 初始化解密器
|
||
cipher.Init(false, keyParamWithIv);
|
||
|
||
// 处理数据
|
||
byte[] output = new byte[cipher.GetOutputSize(ciphertext.Length)];
|
||
int len = cipher.ProcessBytes(ciphertext, 0, ciphertext.Length, output, 0);
|
||
len += cipher.DoFinal(output, len);
|
||
|
||
// 返回正确长度的明文
|
||
if (len < output.Length)
|
||
{
|
||
byte[] result = new byte[len];
|
||
Array.Copy(output, 0, result, 0, len);
|
||
return result;
|
||
}
|
||
|
||
return output;
|
||
}
|
||
#endregion
|
||
|
||
#region ECB加密(PKCS#7填充)
|
||
// SM4 ECB加密(PKCS#7填充)
|
||
public static byte[] Encrypt(byte[] key, byte[] plaintext)
|
||
{
|
||
if (key == null || key.Length != BLOCK_SIZE)
|
||
throw new ArgumentException("Key must be 16 bytes (128 bits)");
|
||
|
||
// 创建加密器
|
||
var engine = new SM4Engine();
|
||
var cipher = new PaddedBufferedBlockCipher(engine, new Pkcs7Padding());
|
||
cipher.Init(true, new KeyParameter(key));
|
||
|
||
// 处理数据
|
||
byte[] output = new byte[cipher.GetOutputSize(plaintext.Length)];
|
||
int len = cipher.ProcessBytes(plaintext, 0, plaintext.Length, output, 0);
|
||
len += cipher.DoFinal(output, len);
|
||
|
||
// 返回正确长度的密文
|
||
if (len < output.Length)
|
||
{
|
||
byte[] result = new byte[len];
|
||
Buffer.BlockCopy(output, 0, result, 0, len);
|
||
return result;
|
||
}
|
||
|
||
return output;
|
||
}
|
||
|
||
// SM4 ECB解密(PKCS#7填充)
|
||
public static byte[] Decrypt(byte[] key, byte[] ciphertext)
|
||
{
|
||
if (key == null || key.Length != BLOCK_SIZE)
|
||
throw new ArgumentException("Key must be 16 bytes (128 bits)");
|
||
|
||
// 创建解密器
|
||
var engine = new SM4Engine();
|
||
var cipher = new PaddedBufferedBlockCipher(engine, new Pkcs7Padding());
|
||
cipher.Init(false, new KeyParameter(key));
|
||
|
||
// 处理数据
|
||
byte[] output = new byte[cipher.GetOutputSize(ciphertext.Length)];
|
||
int len = cipher.ProcessBytes(ciphertext, 0, ciphertext.Length, output, 0);
|
||
len += cipher.DoFinal(output, len);
|
||
|
||
// 返回正确长度的明文
|
||
if (len < output.Length)
|
||
{
|
||
byte[] result = new byte[len];
|
||
Buffer.BlockCopy(output, 0, result, 0, len);
|
||
return result;
|
||
}
|
||
|
||
return output;
|
||
}
|
||
#endregion
|
||
|
||
//// SM2加密
|
||
//public static byte[] SM2Encrypt(byte[] publicKey, byte[] data)
|
||
//{
|
||
// var curve = Org.BouncyCastle.Asn1.GM.GMNamedCurves.GetByName("sm2p256v1");
|
||
// var domainParams = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H);
|
||
|
||
// var q = curve.Curve.DecodePoint(publicKey);
|
||
// var pubKey = new ECPublicKeyParameters(q, domainParams);
|
||
|
||
// var cipher = new SM2Engine(new SM3Digest());
|
||
// cipher.Init(true, new ParametersWithRandom(pubKey, new SecureRandom()));
|
||
|
||
// return cipher.ProcessBlock(data, 0, data.Length);
|
||
//}
|
||
|
||
//// SM2解密
|
||
//public static byte[] SM2Decrypt(byte[] privateKey, byte[] encryptedData)
|
||
//{
|
||
// var curve = Org.BouncyCastle.Asn1.GM.GMNamedCurves.GetByName("sm2p256v1");
|
||
// var domainParams = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H);
|
||
|
||
// var d = new BigInteger(1, privateKey);
|
||
// var privKey = new ECPrivateKeyParameters(d, domainParams);
|
||
|
||
// var cipher = new SM2Engine(new SM3Digest());
|
||
// cipher.Init(false, privKey);
|
||
|
||
// return cipher.ProcessBlock(encryptedData, 0, encryptedData.Length);
|
||
//}
|
||
}
|
||
}
|