编程语言
首页 > 编程语言> > .Net Core关于SM4 加密算法 修正版

.Net Core关于SM4 加密算法 修正版

作者:互联网

最近涉及到了很多关于SM4加密解密的对接要求,说明国密这块有越来越多的人愿意使用了。(题外话)

所以我也网上看了看大家写的加密解密帮助类。也算是对前辈的代码做个实现,最终发现有些地方是有问题的。

这里引用一个博主的文章内容,

引用地址:https://www.cnblogs.com/LowKeyCXY/p/14207819.html  (侵删找我哦!)

 

SM4的介绍和逻辑规则我就不多说了,大家可以去引用的博主里看,代码有几点问题:

1.使用ecb模式时,确实没问题,但碰到CBC时就发现问题了,最总找到了逻辑错误点。

如下图:

 

 

 

这里的i,明显有问题,实际应该是 j * 16 如果使用博主的代码,则会报错(别问我怎么知道的,狗头)

2.博主给的加密后使用的是hex.encode 也就是哈希加密,其实现实中有的地方要求base64.encode也就是base64加密,所以不看代码不行啊。(一直和对接方的数据不一致,说多了都是泪)。

如下图:

 

 

 

好了,话不多说,赶紧上代码:

(本代码仅对CBC做了优化,小伙伴可以自由发挥哈!)

 

  1 using Org.BouncyCastle.Utilities.Encoders;
  2 using System;
  3 using System.Collections.Generic;
  4 using System.Text;
  5 
  6 namespace AirtuBus.Infrastructure.Encryp
  7 {
  8     public class SM4Helper
  9     {
 10         /// <summary>
 11         /// 加密ECB模式
 12         /// </summary>
 13         /// <param name="secretKey">密钥</param>
 14         /// <param name="hexString">明文是否是十六进制</param>
 15         /// <param name="plainText">明文</param>
 16         /// <returns>返回密文</returns>
 17         public static string Encrypt_ECB(string secretKey, bool hexString, string plainText)
 18         {
 19             SM4Context ctx = new SM4Context();
 20             ctx.isPadding = true;
 21             ctx.mode = Sm4.SM4_ENCRYPT;
 22             byte[] keyBytes;
 23             if (hexString)
 24             {
 25                 keyBytes = Hex.Decode(secretKey);
 26             }
 27             else
 28             {
 29                 keyBytes = Encoding.UTF8.GetBytes(secretKey);
 30             }
 31             Sm4 sm4 = new Sm4();
 32             sm4.sm4_setkey_enc(ctx, keyBytes);
 33             byte[] encrypted = sm4.sm4_crypt_ecb(ctx, Encoding.UTF8.GetBytes(plainText));
 34             string cipherText = Encoding.UTF8.GetString(Hex.Encode(encrypted));
 35             return cipherText;
 36         }
 37 
 38         /// <summary>
 39         /// 解密ECB模式
 40         /// </summary>
 41         /// <param name="secretKey">密钥</param>
 42         /// <param name="hexString">明文是否是十六进制</param>
 43         /// <param name="cipherText">密文</param>
 44         /// <returns>返回明文</returns>
 45         public static string Decrypt_ECB(string secretKey, bool hexString, string cipherText)
 46         {
 47             SM4Context ctx = new SM4Context();
 48             ctx.isPadding = true;
 49             ctx.mode = Sm4.SM4_DECRYPT;
 50 
 51             byte[] keyBytes;
 52             if (hexString)
 53             {
 54                 keyBytes = Hex.Decode(secretKey);
 55             }
 56             else
 57             {
 58                 keyBytes = Encoding.UTF8.GetBytes(secretKey);
 59             }
 60 
 61             Sm4 sm4 = new Sm4();
 62             sm4.sm4_setkey_dec(ctx, keyBytes);
 63             byte[] decrypted = sm4.sm4_crypt_ecb(ctx, Hex.Decode(cipherText));
 64             return Encoding.UTF8.GetString(decrypted);
 65         }
 66 
 67         /// <summary>
 68         /// 加密CBC模式
 69         /// </summary>
 70         /// <param name="secretKey">密钥</param>
 71         /// <param name="hexString">明文是否是十六进制</param>
 72         /// <param name="iv"></param>
 73         /// <param name="plainText">明文</param>
 74         /// <returns>返回密文</returns>
 75         public static string Encrypt_CBC(string secretKey, bool hexString, string iv, string plainText, string encoding = "utf-8", int needEnCode = 1)
 76         {
 77             if (encoding.IsNullOrEmpty())
 78             {
 79                 encoding = "utf-8";
 80             }
 81             if (encoding == "GBK" || encoding == "GB2312")
 82             {
 83                 Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
 84             }
 85             SM4Context ctx = new SM4Context();
 86             ctx.isPadding = true;
 87             ctx.mode = Sm4.SM4_ENCRYPT;
 88             byte[] keyBytes;
 89             byte[] ivBytes;
 90             if (hexString)
 91             {
 92                 keyBytes = Hex.Decode(secretKey);
 93                 ivBytes = Hex.Decode(iv);
 94             }
 95             else
 96             {
 97                 keyBytes = Encoding.UTF8.GetBytes(secretKey);
 98                 ivBytes = Encoding.UTF8.GetBytes(iv);
 99             }
100             Sm4 sm4 = new Sm4();
101             sm4.sm4_setkey_enc(ctx, keyBytes);
102             byte[] encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, Encoding.GetEncoding(encoding).GetBytes(plainText));
103             if (needEnCode == 1)
104             {
105                 encrypted = Hex.Encode(encrypted);
106             }else if(needEnCode == 2)
107             {
108                 encrypted = Base64.Encode(encrypted);
109             }
110             string cipherText = Encoding.UTF8.GetString(encrypted);
111             return cipherText;
112         }
113 
114         /// <summary>
115         /// 解密CBC模式
116         /// </summary>
117         /// <param name="secretKey">密钥</param>
118         /// <param name="hexString">明文是否是十六进制</param>
119         /// <param name="iv"></param>
120         /// <param name="cipherText">密文</param>
121         /// <returns>返回明文</returns>
122         public static string Decrypt_CBC(string secretKey, bool hexString, string iv, string cipherText)
123         {
124             SM4Context ctx = new SM4Context();
125             ctx.isPadding = true;
126             ctx.mode = Sm4.SM4_DECRYPT;
127             byte[] keyBytes;
128             byte[] ivBytes;
129             if (hexString)
130             {
131                 keyBytes = Hex.Decode(secretKey);
132                 ivBytes = Hex.Decode(iv);
133             }
134             else
135             {
136                 keyBytes = Encoding.UTF8.GetBytes(secretKey);
137                 ivBytes = Encoding.UTF8.GetBytes(iv);
138             }
139             Sm4 sm4 = new Sm4();
140             sm4.sm4_setkey_dec(ctx, keyBytes);
141             byte[] decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, Hex.Decode(cipherText));
142             return Encoding.UTF8.GetString(decrypted);
143         }
144 
145         /// <summary>
146         /// 加密ECB模式 BASE64
147         /// </summary>
148         /// <param name="secretKey"></param>
149         /// <param name="hexString"></param>
150         /// <param name="plainText"></param>
151         /// <returns></returns>
152         public static string Encrypt_ECB_Base64(string secretKey, bool hexString, string plainText)
153         {
154             SM4Context ctx = new SM4Context();
155             ctx.isPadding = true;
156             ctx.mode = Sm4.SM4_ENCRYPT;
157             byte[] keyBytes;
158             if (hexString)
159             {
160                 keyBytes = Hex.Decode(secretKey);
161             }
162             else
163             {
164                 keyBytes = Encoding.UTF8.GetBytes(secretKey);
165             }
166             Sm4 sm4 = new Sm4();
167             sm4.sm4_setkey_enc(ctx, keyBytes);
168             byte[] encrypted = sm4.sm4_crypt_ecb(ctx, Encoding.UTF8.GetBytes(plainText));
169             string cipherText = Encoding.UTF8.GetString(Base64.Encode(encrypted));
170             return cipherText;
171         }
172 
173         /// <summary>
174         /// 解密ECB模式 BASE64
175         /// </summary>
176         /// <param name="secretKey"></param>
177         /// <param name="hexString"></param>
178         /// <param name="plainText"></param>
179         /// <returns></returns>
180         public static string Decrypt_ECB_Base64(string secretKey, bool hexString, string cipherText)
181         {
182             if (cipherText.IsNullOrEmpty() || secretKey.IsNullOrEmpty()) return null;
183             SM4Context ctx = new SM4Context();
184             ctx.isPadding = true;
185             ctx.mode = Sm4.SM4_DECRYPT;
186 
187             byte[] keyBytes;
188             if (hexString)
189             {
190                 keyBytes = Hex.Decode(secretKey);
191             }
192             else
193             {
194                 keyBytes = Encoding.UTF8.GetBytes(secretKey);
195             }
196 
197             Sm4 sm4 = new Sm4();
198             sm4.sm4_setkey_dec(ctx, keyBytes);
199             byte[] decrypted = sm4.sm4_crypt_ecb(ctx, Base64.Decode(cipherText));
200             return Encoding.UTF8.GetString(decrypted);
201         }
202     }
203 
204     public class Sm4
205     {
206         public const int SM4_ENCRYPT = 1;
207         public const int SM4_DECRYPT = 0;
208 
209         private long GET_ULONG_BE(byte[] b, int i)
210         {
211             long n = (long)(b[i] & 0xff) << 24 | (long)((b[i + 1] & 0xff) << 16) | (long)((b[i + 2] & 0xff) << 8) | (long)(b[i + 3] & 0xff) & 0xffffffffL;
212             return n;
213         }
214         private void PUT_ULONG_BE(long n, byte[] b, int i)
215         {
216             b[i] = (byte)(int)(0xFF & n >> 24);
217             b[i + 1] = (byte)(int)(0xFF & n >> 16);
218             b[i + 2] = (byte)(int)(0xFF & n >> 8);
219             b[i + 3] = (byte)(int)(0xFF & n);
220         }
221         private long SHL(long x, int n)
222         {
223             return (x & 0xFFFFFFFF) << n;
224         }
225         private long ROTL(long x, int n)
226         {
227             return SHL(x, n) | x >> (32 - n);
228         }
229         private void SWAP(long[] sk, int i)
230         {
231             long t = sk[i];
232             sk[i] = sk[(31 - i)];
233             sk[(31 - i)] = t;
234         }
235         public byte[] SboxTable = new byte[] { (byte) 0xd6, (byte) 0x90, (byte) 0xe9, (byte) 0xfe,
236       (byte) 0xcc, (byte) 0xe1, 0x3d, (byte) 0xb7, 0x16, (byte) 0xb6,
237       0x14, (byte) 0xc2, 0x28, (byte) 0xfb, 0x2c, 0x05, 0x2b, 0x67,
238       (byte) 0x9a, 0x76, 0x2a, (byte) 0xbe, 0x04, (byte) 0xc3,
239       (byte) 0xaa, 0x44, 0x13, 0x26, 0x49, (byte) 0x86, 0x06,
240       (byte) 0x99, (byte) 0x9c, 0x42, 0x50, (byte) 0xf4, (byte) 0x91,
241       (byte) 0xef, (byte) 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43,
242       (byte) 0xed, (byte) 0xcf, (byte) 0xac, 0x62, (byte) 0xe4,
243       (byte) 0xb3, 0x1c, (byte) 0xa9, (byte) 0xc9, 0x08, (byte) 0xe8,
244       (byte) 0x95, (byte) 0x80, (byte) 0xdf, (byte) 0x94, (byte) 0xfa,
245       0x75, (byte) 0x8f, 0x3f, (byte) 0xa6, 0x47, 0x07, (byte) 0xa7,
246       (byte) 0xfc, (byte) 0xf3, 0x73, 0x17, (byte) 0xba, (byte) 0x83,
247       0x59, 0x3c, 0x19, (byte) 0xe6, (byte) 0x85, 0x4f, (byte) 0xa8,
248       0x68, 0x6b, (byte) 0x81, (byte) 0xb2, 0x71, 0x64, (byte) 0xda,
249       (byte) 0x8b, (byte) 0xf8, (byte) 0xeb, 0x0f, 0x4b, 0x70, 0x56,
250       (byte) 0x9d, 0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, (byte) 0xd1,
251       (byte) 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, (byte) 0x87,
252       (byte) 0xd4, 0x00, 0x46, 0x57, (byte) 0x9f, (byte) 0xd3, 0x27,
253       0x52, 0x4c, 0x36, 0x02, (byte) 0xe7, (byte) 0xa0, (byte) 0xc4,
254       (byte) 0xc8, (byte) 0x9e, (byte) 0xea, (byte) 0xbf, (byte) 0x8a,
255       (byte) 0xd2, 0x40, (byte) 0xc7, 0x38, (byte) 0xb5, (byte) 0xa3,
256       (byte) 0xf7, (byte) 0xf2, (byte) 0xce, (byte) 0xf9, 0x61, 0x15,
257       (byte) 0xa1, (byte) 0xe0, (byte) 0xae, 0x5d, (byte) 0xa4,
258       (byte) 0x9b, 0x34, 0x1a, 0x55, (byte) 0xad, (byte) 0x93, 0x32,
259       0x30, (byte) 0xf5, (byte) 0x8c, (byte) 0xb1, (byte) 0xe3, 0x1d,
260       (byte) 0xf6, (byte) 0xe2, 0x2e, (byte) 0x82, 0x66, (byte) 0xca,
261       0x60, (byte) 0xc0, 0x29, 0x23, (byte) 0xab, 0x0d, 0x53, 0x4e, 0x6f,
262       (byte) 0xd5, (byte) 0xdb, 0x37, 0x45, (byte) 0xde, (byte) 0xfd,
263       (byte) 0x8e, 0x2f, 0x03, (byte) 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b,
264       0x51, (byte) 0x8d, 0x1b, (byte) 0xaf, (byte) 0x92, (byte) 0xbb,
265       (byte) 0xdd, (byte) 0xbc, 0x7f, 0x11, (byte) 0xd9, 0x5c, 0x41,
266       0x1f, 0x10, 0x5a, (byte) 0xd8, 0x0a, (byte) 0xc1, 0x31,
267       (byte) 0x88, (byte) 0xa5, (byte) 0xcd, 0x7b, (byte) 0xbd, 0x2d,
268       0x74, (byte) 0xd0, 0x12, (byte) 0xb8, (byte) 0xe5, (byte) 0xb4,
269       (byte) 0xb0, (byte) 0x89, 0x69, (byte) 0x97, 0x4a, 0x0c,
270       (byte) 0x96, 0x77, 0x7e, 0x65, (byte) 0xb9, (byte) 0xf1, 0x09,
271       (byte) 0xc5, 0x6e, (byte) 0xc6, (byte) 0x84, 0x18, (byte) 0xf0,
272       0x7d, (byte) 0xec, 0x3a, (byte) 0xdc, 0x4d, 0x20, 0x79,
273       (byte) 0xee, 0x5f, 0x3e, (byte) 0xd7, (byte) 0xcb, 0x39, 0x48 };
274         public uint[] FK = { 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc };
275         public uint[] CK = { 0x00070e15,0x1c232a31,0x383f464d,0x545b6269,
276                     0x70777e85,0x8c939aa1,0xa8afb6bd,0xc4cbd2d9,
277                     0xe0e7eef5,0xfc030a11,0x181f262d,0x343b4249,
278                     0x50575e65,0x6c737a81,0x888f969d,0xa4abb2b9,
279                     0xc0c7ced5,0xdce3eaf1,0xf8ff060d,0x141b2229,
280                     0x30373e45,0x4c535a61,0x686f767d,0x848b9299,
281                     0xa0a7aeb5,0xbcc3cad1,0xd8dfe6ed,0xf4fb0209,
282                     0x10171e25,0x2c333a41,0x484f565d,0x646b7279 };
283         private byte sm4Sbox(byte inch)
284         {
285             int i = inch & 0xFF;
286             byte retVal = SboxTable[i];
287             return retVal;
288         }
289         private long sm4Lt(long ka)
290         {
291             long bb = 0L;
292             long c = 0L;
293             byte[] a = new byte[4];
294             byte[] b = new byte[4];
295             PUT_ULONG_BE(ka, a, 0);
296             b[0] = sm4Sbox(a[0]);
297             b[1] = sm4Sbox(a[1]);
298             b[2] = sm4Sbox(a[2]);
299             b[3] = sm4Sbox(a[3]);
300             bb = GET_ULONG_BE(b, 0);
301             c = bb ^ ROTL(bb, 2) ^ ROTL(bb, 10) ^ ROTL(bb, 18) ^ ROTL(bb, 24);
302             return c;
303         }
304         private long sm4F(long x0, long x1, long x2, long x3, long rk)
305         {
306             return x0 ^ sm4Lt(x1 ^ x2 ^ x3 ^ rk);
307         }
308 
309         private long sm4CalciRK(long ka)
310         {
311             long bb = 0L;
312             long rk = 0L;
313             byte[] a = new byte[4];
314             byte[] b = new byte[4];
315             PUT_ULONG_BE(ka, a, 0);
316             b[0] = sm4Sbox(a[0]);
317             b[1] = sm4Sbox(a[1]);
318             b[2] = sm4Sbox(a[2]);
319             b[3] = sm4Sbox(a[3]);
320             bb = GET_ULONG_BE(b, 0);
321             rk = bb ^ ROTL(bb, 13) ^ ROTL(bb, 23);
322             return rk;
323         }
324 
325         private void sm4_setkey(long[] SK, byte[] key)
326         {
327             long[] MK = new long[4];
328             long[] k = new long[36];
329             int i = 0;
330             MK[0] = GET_ULONG_BE(key, 0);
331             MK[1] = GET_ULONG_BE(key, 4);
332             MK[2] = GET_ULONG_BE(key, 8);
333             MK[3] = GET_ULONG_BE(key, 12);
334             k[0] = MK[0] ^ (long)FK[0];
335             k[1] = MK[1] ^ (long)FK[1];
336             k[2] = MK[2] ^ (long)FK[2];
337             k[3] = MK[3] ^ (long)FK[3];
338             for (; i < 32; i++)
339             {
340                 k[(i + 4)] = (k[i] ^ sm4CalciRK(k[(i + 1)] ^ k[(i + 2)] ^ k[(i + 3)] ^ (long)CK[i]));
341                 SK[i] = k[(i + 4)];
342             }
343         }
344 
345         private void sm4_one_round(long[] sk, byte[] input, byte[] output)
346         {
347             int i = 0;
348             long[] ulbuf = new long[36];
349             ulbuf[0] = GET_ULONG_BE(input, 0);
350             ulbuf[1] = GET_ULONG_BE(input, 4);
351             ulbuf[2] = GET_ULONG_BE(input, 8);
352             ulbuf[3] = GET_ULONG_BE(input, 12);
353             while (i < 32)
354             {
355                 ulbuf[(i + 4)] = sm4F(ulbuf[i], ulbuf[(i + 1)], ulbuf[(i + 2)], ulbuf[(i + 3)], sk[i]);
356                 i++;
357             }
358             PUT_ULONG_BE(ulbuf[35], output, 0);
359             PUT_ULONG_BE(ulbuf[34], output, 4);
360             PUT_ULONG_BE(ulbuf[33], output, 8);
361             PUT_ULONG_BE(ulbuf[32], output, 12);
362         }
363 
364         private byte[] padding(byte[] input, int mode)
365         {
366             if (input == null)
367             {
368                 return null;
369             }
370 
371             byte[] ret = (byte[])null;
372             if (mode == SM4_ENCRYPT)
373             {
374                 int p = 16 - input.Length % 16;
375                 ret = new byte[input.Length + p];
376                 Array.Copy(input, 0, ret, 0, input.Length);
377                 for (int i = 0; i < p; i++)
378                 {
379                     ret[input.Length + i] = (byte)p;
380                 }
381             }
382             else
383             {
384                 int p = input[input.Length - 1];
385                 ret = new byte[input.Length - p];
386                 Array.Copy(input, 0, ret, 0, input.Length - p);
387             }
388             return ret;
389         }
390 
391         public void sm4_setkey_enc(SM4Context ctx, byte[] key)
392         {
393             ctx.mode = SM4_ENCRYPT;
394             sm4_setkey(ctx.sk, key);
395         }
396 
397         public void sm4_setkey_dec(SM4Context ctx, byte[] key)
398         {
399             int i = 0;
400             ctx.mode = SM4_DECRYPT;
401             sm4_setkey(ctx.sk, key);
402             for (i = 0; i < 16; i++)
403             {
404                 SWAP(ctx.sk, i);
405             }
406         }
407 
408         public byte[] sm4_crypt_ecb(SM4Context ctx, byte[] input)
409         {
410             if ((ctx.isPadding) && (ctx.mode == SM4_ENCRYPT))
411             {
412                 input = padding(input, SM4_ENCRYPT);
413             }
414 
415             int length = input.Length;
416             byte[] bins = new byte[length];
417             Array.Copy(input, 0, bins, 0, length);
418             byte[] bous = new byte[length];
419             for (int i = 0; length > 0; length -= 16, i++)
420             {
421                 byte[] inBytes = new byte[16];
422                 byte[] outBytes = new byte[16];
423                 Array.Copy(bins, i * 16, inBytes, 0, length > 16 ? 16 : length);
424                 sm4_one_round(ctx.sk, inBytes, outBytes);
425                 Array.Copy(outBytes, 0, bous, i * 16, length > 16 ? 16 : length);
426             }
427 
428             if (ctx.isPadding && ctx.mode == SM4_DECRYPT)
429             {
430                 bous = padding(bous, SM4_DECRYPT);
431             }
432             return bous;
433         }
434 
435         public byte[] sm4_crypt_cbc(SM4Context ctx, byte[] iv, byte[] input)
436         {
437             if (ctx.isPadding && ctx.mode == SM4_ENCRYPT)
438             {
439                 input = padding(input, SM4_ENCRYPT);
440             }
441 
442             int i = 0;
443             int length = input.Length;
444             byte[] bins = new byte[length];
445             Array.Copy(input, 0, bins, 0, length);
446             byte[] bous = null;
447             List<byte> bousList = new List<byte>();
448             if (ctx.mode == SM4_ENCRYPT)
449             {
450                 for (int j = 0; length > 0; length -= 16, j++)
451                 {
452                     byte[] inBytes = new byte[16];
453                     byte[] outBytes = new byte[16];
454                     byte[] out1 = new byte[16];
455                     Array.Copy(bins, j * 16, inBytes, 0, length > 16 ? 16 : length);
456                     for (i = 0; i < 16; i++)
457                     {
458                         outBytes[i] = ((byte)(inBytes[i] ^ iv[i]));
459                     }
460                     sm4_one_round(ctx.sk, outBytes, out1);
461                     Array.Copy(out1, 0, iv, 0, 16);
462                     for (int k = 0; k < 16; k++)
463                     {
464                         bousList.Add(out1[k]);
465                     }
466                 }
467             }
468             else
469             {
470                 byte[] temp = new byte[16];
471                 for (int j = 0; length > 0; length -= 16, j++)
472                 {
473                     byte[] inBytes = new byte[16];
474                     byte[] outBytes = new byte[16];
475                     byte[] out1 = new byte[16];
476 
477 
478                     Array.Copy(bins, i * 16, inBytes, 0, length > 16 ? 16 : length);
479                     Array.Copy(inBytes, 0, temp, 0, 16);
480                     sm4_one_round(ctx.sk, inBytes, outBytes);
481                     for (i = 0; i < 16; i++)
482                     {
483                         out1[i] = ((byte)(outBytes[i] ^ iv[i]));
484                     }
485                     Array.Copy(temp, 0, iv, 0, 16);
486                     for (int k = 0; k < 16; k++)
487                     {
488                         bousList.Add(out1[k]);
489                     }
490                 }
491             }
492             if (ctx.isPadding && ctx.mode == SM4_DECRYPT)
493             {
494                 bous = padding(bousList.ToArray(), SM4_DECRYPT);
495                 return bous;
496             }
497             else
498             {
499                 return bousList.ToArray();
500             }
501         }
502     }
503 
504     public class SM4Context
505     {
506         public int mode;
507         public long[] sk;
508         public bool isPadding;
509         public SM4Context()
510         {
511             this.mode = 1;
512             this.isPadding = true;
513             this.sk = new long[32];
514         }
515     }
516 }

 

标签:Core,sm4,16,SM4,ctx,long,new,byte,加密算法
来源: https://www.cnblogs.com/iainYang/p/16106581.html