與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 }