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