.NET SM4 算法

与DES和AES算法相似,国密SM4算法是一种分组加密算法。SM4分组密码算法是一种迭代分组密码算法,由加解密算法和密钥扩展算法组成。

SM4是一种Feistel结构的分组密码算法,其分组长度和密钥长度均为128bits。加密算法和密钥扩展算法迭代轮数均为32轮。SM4加解密过程的算法相同但是轮密钥的使用顺序相反。

SM4密码算法使用模2加和循环移位作为基本运算。

密钥扩展算法:SM4算法使用128位的加密密钥,并采用32轮迭代加密结构,每一轮加密使用一个32位的轮密钥,总共使用32个轮密钥。因此需要使用密钥扩展算法,从加密密钥中产生32个轮密钥。

SM4加解密流程

SM4算法的加密大致流程如下:

密钥:加密密钥的长度为128比特,表示为MK = (MK0, MK1, MK2, MK3),其中MKi为32位,轮密钥表示为(rk0, rk1, ……, rk31),其中rki为32位。

轮函数F:假设输入为(X0, X1, X2, X3),X为32位,则轮函数F为:F=(X0, X1, X2, X3, rk) = X0 ⊕ T(X1 ⊕ X2 ⊕ X3 ⊕ rk)

合成置换:T函数是一个可逆变换,由一个非线性变换r和线性变换L复合而成的,即T( )=L(r( ))

非线性变换有四个并行的S盒构成的,设输入为A=(a0, a1, a2, a3),输出为B=(b0, b1, b2, b3),其中ai和bi为8位。每个S盒的输入都是一个8位的字节,将这8位的前四位对应的16进制数作为行编号,后四位对应的16进制数作为列编号,然后用相应位置中的字节代替输入的字节。下图为S盒置换表:

 

线性变换L:线形变换的输入就是S盒的输出,即C=L(B)=B ⊕ (B<<<2) ⊕ (B<<<10) ⊕ (B<<<18) ⊕ (B<<<24),线性变换的输入和输出都是32位的。

经过了32轮的迭代运算后,最后再进行一次反序变换即可得到加密的密文,即密文C=(Y0, Y1, Y2, Y3)=R(X32. X33, X34, X35)=(X35, X34, X33, X32)。

SM4算法的解密流程和加密流程一致,只不过轮密钥的使用顺序变成了(rk31, rk30, ……, rk0)

密钥扩展算法

密钥参量:轮密钥由加密密钥生成。FK=(FK0, FK1, FK2, FK3)为系统参数,以及固定参数CK=(CK0, CK1, ……,  CK31),其中FKi和CKi均为32位并用于密钥扩展算法。

系统参数FK的具体取值如下:

FK0=(A3B1BAC6), FK1=(56AA3350), FK2=(677D9197), FK3=(B27022DC)

固定参数CK的具体取值如下:

密钥扩展方法:设(K0, K1, K2, K3)=(MK0⊕FK0, MK1⊕FK1, MK2⊕FK2, MK3⊕FK3)

则rki=Ki+4=Ki⊕T‘(Ki+1⊕Ki+2⊕Ki+3⊕CKi)

其中T’()是将原来的T()中的线形变换L()替换成L'(B)=B⊕(B<<<13)⊕(B<<<23)

 

废话不多说直接上代码

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

 

 

 1 using System;
 2 using System.Collections.Generic;
 3 using System.IO;
 4 using System.Security.Cryptography;
 5 using System.Text;
 6 
 7 namespace SM
 8 {
 9 
10     public class SignUtil
11     {
12 
13         public static string EncryptData(string appSecret, string data)
14         {
15             var sm4 = new MainSm4();
16 
17             return sm4.EncryptECB(appSecret, true, data);
18         }
19 
20         public static string DecryptData(string appSecret, string data)
21         {
22             var sm4 = new MainSm4();
23             return sm4.DecryptECB(appSecret, true, data);
24         }
25 
26         public static string MarkSign(string signType, Dictionary<string, string> paramDic)
27         {
28             if (paramDic == null || paramDic.Count == 0)
29             {
30                 throw new Exception("签名参数不能为空");
31             }
32 
33             StringBuilder sbStr = new StringBuilder();
34             foreach (var param in paramDic)
35             {
36                 sbStr.Append(param.Value);
37             }
38 
39             string beforeSignStr = sbStr.Append(signType).ToString();
40 
41             if (signType == "MD5")
42             {
43                 return Md5Hex(beforeSignStr);
44             }
45 
46             throw new Exception("未实现加密方式");
47         }
48 
49         private static string Md5Hex(string data)
50         {
51             MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
52             byte[] dataHash = md5.ComputeHash(Encoding.UTF8.GetBytes(data));
53             StringBuilder sb = new StringBuilder();
54             foreach (byte b in dataHash)
55             {
56                 sb.Append(b.ToString("x2").ToLower());
57             }
58             return sb.ToString();
59         }
60 
61         /**
62         * 生成时间戳,标准北京时间,时区为东八区,自1970年1月1日 0点0分0秒以来的秒数
63          * @return 时间戳
64         */
65         public static string GenerateTimeStamp()
66         {
67             TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
68             return Convert.ToInt64(ts.TotalSeconds).ToString();
69         }
70     }
71 }

 

版权声明:本文为LowKeyCXY原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/LowKeyCXY/p/14207819.html