一種C# 的SM4 的 加解密的實現
一般用于醫療或者支付
加密
?string cipherText = SM4Helper.Encrypt_test(data, key);
? ? ? ? public static string Encrypt_test(string plainText, string key)
? ? ? ? {
? ? ? ? ? ? byte[] keyBytes = Encoding.ASCII.GetBytes(key);
? ? ? ? ? ? byte[] inputBytes = Encoding.UTF8.GetBytes(plainText);
? ? ? ? ? ? // 初始化SM4引擎
? ? ? ? ? ? var engine = new SM4Engine();
? ? ? ? ? ? var cipher = new PaddedBufferedBlockCipher(engine, new Pkcs7Padding());
? ? ? ? ? ? cipher.Init(true, new KeyParameter(keyBytes));
? ? ? ? ? ? // 執行加密
? ? ? ? ? ? byte[] output = new byte[cipher.GetOutputSize(inputBytes.Length)];
? ? ? ? ? ? int len = cipher.ProcessBytes(inputBytes, 0, inputBytes.Length, output, 0);
? ? ? ? ? ? cipher.DoFinal(output, len);
? ? ? ? ? ? // 轉換為大寫十六進制字符串
? ? ? ? ? ? return BitConverter.ToString(output).Replace("-", "").ToUpper();
? ? ? ? }
解密
string decryptedText = SM4Helper.Decrypt_test(cipherText, key);
? public static string Decrypt_test(string plainText, string key)
? ? ? ? {
? ? ? ? ? ? byte[] keyBytes = Encoding.ASCII.GetBytes(key);
? ? ? ? ? ? byte[] inputBytes = FromHexString(plainText);
? ? ? ? ? ? // 初始化SM4引擎
? ? ? ? ? ? var engine = new SM4Engine(); ?
? ? ? ? ? ? var cipher = new PaddedBufferedBlockCipher(engine, new Pkcs7Padding());
? ? ? ? ? ? cipher.Init(false, new KeyParameter(keyBytes)); // false表示解密模式
? ? ? ? ? ? // 執行解密
? ? ? ? ? ? byte[] output = new byte[cipher.GetOutputSize(inputBytes.Length)];
? ? ? ? ? ? int len = cipher.ProcessBytes(inputBytes, 0, inputBytes.Length, output, 0);
? ? ? ? ? ? len += cipher.DoFinal(output, len);
? ? ? ? ? ? // 移除可能的填充字節
? ? ? ? ? ? byte[] result = new byte[len];
? ? ? ? ? ? Array.Copy(output, result, len);
? ? ? ? ? ? return Encoding.UTF8.GetString(result);
? ? ? ? }
SM4Helper 的全部代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Globalization;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Paddings;
using Org.BouncyCastle.Crypto.Parameters;namespace OneClikPay
{public class SM4Helper{/// <summary>/// SM4加密(ECB模式,PKCS7填充)/// </summary>public static string Encrypt(string plainText, string hexKey){byte[] keyBytes = FromHexString(hexKey); // 使用嚴格兼容的十六進制轉換byte[] plainBytes = Encoding.UTF8.GetBytes(plainText);var cipher = CreateCipher(true, keyBytes);byte[] encrypted = cipher.DoFinal(plainBytes);return BytesToHex(encrypted);}/// <summary>/// SM4解密(ECB模式,PKCS7填充)/// </summary>public static string Decrypt(string hexCipherText, string hexKey){byte[] keyBytes = FromHexString(hexKey);byte[] cipherBytes = FromHexString(hexCipherText);var cipher = CreateCipher(false, keyBytes);byte[] decrypted = cipher.DoFinal(cipherBytes);return Encoding.UTF8.GetString(decrypted);}#region 核心加密模塊private static BufferedBlockCipher CreateCipher(bool forEncryption, byte[] key){// 嚴格校驗密鑰長度if (key.Length != 16)throw new ArgumentException("密鑰必須為128位(16字節)");IBlockCipher engine = new SM4Engine();var cipher = new PaddedBufferedBlockCipher(new EcbBlockCipher(engine), new Pkcs7Padding());cipher.Init(forEncryption, new KeyParameter(key));return cipher;}#endregion#region 完全兼容Java的十六進制轉換(ByteUtils.fromHexString等效實現)public static byte[] FromHexString(string hex){if (hex == null)throw new ArgumentNullException(nameof(hex));hex = hex.Trim().Replace(" ", "").Replace("\n", "").Replace("\t", "");if (hex.Length % 2 != 0)throw new FormatException("十六進制字符串長度必須為偶數");byte[] bytes = new byte[hex.Length / 2];for (int i = 0; i < bytes.Length; i++){string hexByte = hex.Substring(i * 2, 2);if (!IsHexChar(hexByte[0]) || !IsHexChar(hexByte[1]))throw new FormatException($"非法十六進制字符: {hexByte}");bytes[i] = byte.Parse(hexByte, NumberStyles.HexNumber, CultureInfo.InvariantCulture);}return bytes;}private static bool IsHexChar(char c){return (c >= '0' && c <= '9') ||(c >= 'a' && c <= 'f') ||(c >= 'A' && c <= 'F');}private static string BytesToHex(byte[] bytes){StringBuilder hex = new StringBuilder(bytes.Length * 2);foreach (byte b in bytes){hex.AppendFormat("{0:X2}", b); // 強制大寫,與Java的Hex.toHexString()一致}return hex.ToString();}#endregionpublic static string Encrypt_test(string plainText, string key){byte[] keyBytes = Encoding.ASCII.GetBytes(key);byte[] inputBytes = Encoding.UTF8.GetBytes(plainText);// 初始化SM4引擎var engine = new SM4Engine();var cipher = new PaddedBufferedBlockCipher(engine, new Pkcs7Padding());cipher.Init(true, new KeyParameter(keyBytes));// 執行加密byte[] output = new byte[cipher.GetOutputSize(inputBytes.Length)];int len = cipher.ProcessBytes(inputBytes, 0, inputBytes.Length, output, 0);cipher.DoFinal(output, len);// 轉換為大寫十六進制字符串return BitConverter.ToString(output).Replace("-", "").ToUpper();}public static string Decrypt_test(string plainText, string key){byte[] keyBytes = Encoding.ASCII.GetBytes(key);byte[] inputBytes = FromHexString(plainText);// 初始化SM4引擎var engine = new SM4Engine(); var cipher = new PaddedBufferedBlockCipher(engine, new Pkcs7Padding());cipher.Init(false, new KeyParameter(keyBytes)); // false表示解密模式// 執行解密byte[] output = new byte[cipher.GetOutputSize(inputBytes.Length)];int len = cipher.ProcessBytes(inputBytes, 0, inputBytes.Length, output, 0);len += cipher.DoFinal(output, len);// 移除可能的填充字節byte[] result = new byte[len];Array.Copy(output, result, len);return Encoding.UTF8.GetString(result);}}
}