You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

196 lines
6.7 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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);
//}
}
}