c# SM4加解密

发布时间 2024-01-03 10:51:16作者: 凉生凉忆亦凉心
 public class SM4Util
 {
     public static void Test()
     {
         //自定义秘钥
         string key = "fb85f951b1cd5542"; string iv = "";
         key = Hex.ToHexString(Encoding.UTF8.GetBytes(key));
         //随机生成的HexString
         GenerateKeyHex(out key, out iv);
         string signTime = DateTimeOffset.Now.ToUnixTimeSeconds().ToString();

         //ECB加密
         var encrypted = SM4Util.ECBEncrypt(Encoding.UTF8.GetBytes(signTime), key);
         string base64 = Convert.ToBase64String(encrypted);
         string sign = Hex.ToHexString(encrypted);
         //ECB解密
         var original = SM4Util.ECBDecrypt(encrypted, key);
         string result = Encoding.UTF8.GetString(original);

         //CBC
         //var encrypted = SM4Util.CBCEncrypt(Encoding.UTF8.GetBytes(signTime), key, iv);
         //string base64 = Convert.ToBase64String(encrypted);
         //string sign = Hex.ToHexString(encrypted);
         //var original = SM4Util.CBCDecrypt(encrypted, key, iv);
         //string result = Encoding.UTF8.GetString(original);
     }

     public static void GenerateKeyHex(out string key, out string iv)
     {
         //用于生成对称加密算法
         var keyGenerator = new CipherKeyGenerator();
         keyGenerator.Init(new KeyGenerationParameters(new SecureRandom(), 128));
         var a = keyGenerator.GenerateKey();
         key = Hex.ToHexString(a);

         SecureRandom random = new SecureRandom();
         byte[] b = new byte[16]; // IV长度为16字节
         random.NextBytes(b);
         iv = Hex.ToHexString(b);
     }

     public static byte[] ECBEncrypt(byte[] input, string key)
     {
         var engine = new SM4Engine();
         var cipher = new PaddedBufferedBlockCipher(engine, new Pkcs7Padding());
         KeyParameter keyParam = new KeyParameter(Decode(key));
         cipher.Init(true, keyParam);

         var output = new byte[cipher.GetOutputSize(input.Length)];
         int length = cipher.ProcessBytes(input, 0, input.Length, output, 0);
         cipher.DoFinal(output, length);

         return output;
     }
     public static byte[] ECBDecrypt(byte[] input, string key)
     {
         var engine = new SM4Engine();
         var cipher = new PaddedBufferedBlockCipher(engine, new Pkcs7Padding());
         KeyParameter keyParam = new KeyParameter(Decode(key));
         cipher.Init(false, keyParam);

         var output = new byte[cipher.GetOutputSize(input.Length)];
         int length = cipher.ProcessBytes(input, 0, input.Length, output, 0);
         cipher.DoFinal(output, length);
         return RemovePadding(output);
     }

     public static byte[] CBCEncrypt(byte[] plaintext, string key, string iv)
     {
         IBufferedCipher cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(new SM4Engine()), new Pkcs7Padding());
         cipher.Init(true, new ParametersWithIV(new KeyParameter(Decode(key)), Decode(iv)));
         byte[] output = new byte[cipher.GetOutputSize(plaintext.Length)];
         int bytesProcessed = cipher.ProcessBytes(plaintext, 0, plaintext.Length, output, 0);
         cipher.DoFinal(output, bytesProcessed);
         return output;
     }
     public static byte[] CBCDecrypt(byte[] ciphertext, string key, string iv)
     {
         IBufferedCipher cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(new SM4Engine()), new Pkcs7Padding());
         cipher.Init(false, new ParametersWithIV(new KeyParameter(Decode(key)), Decode(iv)));
         byte[] output = new byte[cipher.GetOutputSize(ciphertext.Length)];
         int bytesProcessed = cipher.ProcessBytes(ciphertext, 0, ciphertext.Length, output, 0);
         cipher.DoFinal(output, bytesProcessed);
         return RemovePadding(output);
     }

     // 去除填充字符
     public static byte[] RemovePadding(byte[] data)
     {
         int lastNonZeroByte = data.Length - 1;
         while (data[lastNonZeroByte] == 0)
         {
             lastNonZeroByte--;
         }
         // 截取非零字节之前的所有字节
         byte[] result = new byte[lastNonZeroByte + 1];
         Array.Copy(data, result, lastNonZeroByte + 1);
         return result;
     }

     static byte[] Decode(string key)
     {
         return Regex.IsMatch(key, "^[0-9a-f]+$", RegexOptions.IgnoreCase) ? Hex.Decode(key) : Convert.FromBase64String(key);
     }
 }