关于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),Xi 为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 }