国密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 }

关于SM4 加密算法的更多相关文章

  1. SM4加密算法实现Java和C#相互加密解密

    SM4加密算法实现Java和C#相互加密解密 近期由于项目需要使用SM4对数据进行加密,然后传给Java后台,Java后台使用的也是SM4的加密算法但是就是解密不正确,经过一步步调试发现Java中好多 ...

  2. 国密SM4分组加密算法实现 (C++)

    原博客 :http://blog.csdn.net/archimekai/article/details/53095993 密码学的一次课程设计,学习了SM4加密算法,目前应用于无线网安全. SM4分 ...

  3. 一文带你学会国产加密算法SM4的java实现方案

    前言 今天给大家带来一个国产SM4加密解密算法的java后端解决方案,代码完整,可以直接使用,希望给大家带来帮助,尤其是做政府系统的开发人员,可以直接应用到项目中进行加密解密. 画重点!是SM4哦,不 ...

  4. 一文带你学会国产加密算法SM4的vue实现方案

    前言 上篇文章我们介绍了国产SM4加密算法的后端java实现方案.没有看过的小伙伴可以看一下这篇文章. https://www.cnblogs.com/jichi/p/12907453.html 本篇 ...

  5. SM4密码算法(附源码)

    SM4是我们自己国家的一个分组密码算法,是国家密码管理局于2012年发布的.网址戳→_→:http://www.cnnic.NET.cn/jscx/mixbz/sm4/ 具体的密码标准和算法官方有非常 ...

  6. java sm4国密算法加密、解密

      java sm4国密算法加密.解密 CreationTime--2018年7月5日09点20分 Author:Marydon 1.准备工作 所需jar包: bcprov-jdk15on-1.59. ...

  7. 基于crypto++国产加密软件SM4的实现,顺带加了ase,base64

    唔,美国压制得越狠,各种替代产品就越能活. 本文分享SM4的一种快速实现与集成方式.             SM4(原名SMS4)是中华人民共和国政府采用的一种分组密码标准,由国家密码管理局于201 ...

  8. sm4算法(附源码、测试代码)

    from:http://blog.csdn.net/mao0514/article/details/52930944 SM4是我们自己国家的一个分组密码算法,是国家密码管理局于2012年发布的.网址戳 ...

  9. stm32——NFC芯片--PN532的使用

    stm32——NFC芯片--PN532的使用 一.NFC简介 NFC(Near Field Communication)近场通信,是一种短距高频的无线电技术,在13.56MHz频率运行于20厘米距离内 ...

随机推荐

  1. 课时四:Action操作

    参考文档 瑞泰信息技术有限公司 微软MVP(15-18)罗勇 语义说明 核心名词 ​ FetchXML:是基于Xml的查询语言,可以把它简单理解成SQL语句,通过它可以查询Dynamics 365 C ...

  2. python 子进程

    1.线程的介绍(理论部分) 1.1 进程线程分工 我们之前讲运行一个py文件,就是开启了一个进程,在内存中开辟一个进程空间,将必要的数据加载到这个进程空间,然后cpu在去调用这个进程的主线程去执行具体 ...

  3. 第4.2节 神秘而强大的Python生成器精讲

    一. 生成器(generator)概念 生成器是一个特殊的迭代器,它保存的是算法,每次调用next()或send()就计算出下一个元素的值,直到计算出最后一个元素,没有更多的元素时,抛出StopIte ...

  4. 转:HTTP协议简介与在python中的使用详解

    1. 使用谷歌/火狐浏览器分析 在Web应用中,服务器把网页传给浏览器,实际上就是把网页的HTML代码发送给浏览器,让浏览器显示出来.而浏览器和服务器之间的传输协议是HTTP,所以: HTML是一种用 ...

  5. PyQt(Python+Qt)学习随笔:QTableWidgetItem项的复选状态checkState访问方法

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 QTableWidget表格部件中的QTableWidgetItem项可以单独设置复选状态,如图所有 ...

  6. 第11.21节 Python 中正则表达式的其他扩展功能

    一. 引言 在<第11.17节 Python 正则表达式扩展功能:命名组功能及组的反向引用>中老猿介绍了组匹配模式的命名组功能及引用组功能,这两者都是正则表达式的扩展功能,其实在re模块中 ...

  7. PyQt(Python+Qt)学习随笔:PyQt帮助文档导入assistant后离线查阅

    在按照<第15.6节 PyQt5安装与配置>完成PyQt5及PyQt5-tools的安装后,发现Qt Designer中的帮助不能使用,报错: 按照<PyQt学习随笔:Qt Desi ...

  8. jarvisoj flag在管理员手上

    jarvisoj flag在管理员手上 涉及知识点: (1)代码审计和cookie注入 (2)哈希长度拓展攻击 解析: 进入题目的界面.看到 那么就是想方设法的变成admin了.挂上御剑开始审计.发现 ...

  9. 【Tomcat 源码系列】源码构建 Tomcat

    一,前言 这篇博客写于 12 月 12 日,从 github[1] 上 fork 了一份 tomcat 的源代码,clone 到了本地.最近想把 tomcat 的源代码分析一下,寒假的时候有完整的时间 ...

  10. Python 学习笔记 之 02 - 高级特性总结

    切片 语法:  li.[x:y:z]  li为list.tuple等数据类型,x为开始进行切片的位置,y为切片停止的位置(不包含y),z为xy切片后的结果里,每间隔z个元素输出一次结果.  x默认为0 ...