关于SM4 加密算法
国密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 }
关于SM4 加密算法的更多相关文章
- SM4加密算法实现Java和C#相互加密解密
SM4加密算法实现Java和C#相互加密解密 近期由于项目需要使用SM4对数据进行加密,然后传给Java后台,Java后台使用的也是SM4的加密算法但是就是解密不正确,经过一步步调试发现Java中好多 ...
- 国密SM4分组加密算法实现 (C++)
原博客 :http://blog.csdn.net/archimekai/article/details/53095993 密码学的一次课程设计,学习了SM4加密算法,目前应用于无线网安全. SM4分 ...
- 一文带你学会国产加密算法SM4的java实现方案
前言 今天给大家带来一个国产SM4加密解密算法的java后端解决方案,代码完整,可以直接使用,希望给大家带来帮助,尤其是做政府系统的开发人员,可以直接应用到项目中进行加密解密. 画重点!是SM4哦,不 ...
- 一文带你学会国产加密算法SM4的vue实现方案
前言 上篇文章我们介绍了国产SM4加密算法的后端java实现方案.没有看过的小伙伴可以看一下这篇文章. https://www.cnblogs.com/jichi/p/12907453.html 本篇 ...
- SM4密码算法(附源码)
SM4是我们自己国家的一个分组密码算法,是国家密码管理局于2012年发布的.网址戳→_→:http://www.cnnic.NET.cn/jscx/mixbz/sm4/ 具体的密码标准和算法官方有非常 ...
- java sm4国密算法加密、解密
java sm4国密算法加密.解密 CreationTime--2018年7月5日09点20分 Author:Marydon 1.准备工作 所需jar包: bcprov-jdk15on-1.59. ...
- 基于crypto++国产加密软件SM4的实现,顺带加了ase,base64
唔,美国压制得越狠,各种替代产品就越能活. 本文分享SM4的一种快速实现与集成方式. SM4(原名SMS4)是中华人民共和国政府采用的一种分组密码标准,由国家密码管理局于201 ...
- sm4算法(附源码、测试代码)
from:http://blog.csdn.net/mao0514/article/details/52930944 SM4是我们自己国家的一个分组密码算法,是国家密码管理局于2012年发布的.网址戳 ...
- stm32——NFC芯片--PN532的使用
stm32——NFC芯片--PN532的使用 一.NFC简介 NFC(Near Field Communication)近场通信,是一种短距高频的无线电技术,在13.56MHz频率运行于20厘米距离内 ...
随机推荐
- rest-framework 版本控制
一 作用: 用于版本的控制 二 内置的版本控制类: from rest_framework.versioning import QueryParameterVersioning,AcceptHeade ...
- 面试官:说一下List排序方法
1. 前言 排序算是比较高频的面试题了,节前面试了的两家公司都有问到排序问题,整理后分享给大家(文末见总结). 通常我们想到实现排序就是 Collections 工具类的 sort() 方法,而 so ...
- windows服务器下tomcat 8.0 配置远程调试
在tomcat的bin目录下, 添加debug.txt文件, 然后输入: set JPDA_ADDRESS=9901set JPDA_TRANSPORT=dt_socketset CATALINA_O ...
- Python函数独立星号(*)分隔的命名关键字参数
如果需要限制关键字参数的输入名字,就需要使用到命名关键字参数的形式,所谓命名关键字参数就是给关键字参数限定指定的名字,输入其他名字不能识别.命名关键字参数和位置参数之间使用独立的星号(*)分隔,星号后 ...
- Xmind常用的快捷键
1.Xmind常用的快捷键 DEL --删除 TAB--新增下一级主题 ENTER--新建同级主题 Ctrl+I--插入图片 Ctrl+f --查找.替换 空格--当前主题内容编辑 通过概要.格式.联 ...
- bugkuctf 这 是 一 个 神 奇 的 登 录 界 面
首先结合源码可以看出这是一道sql注入题. 然后开始萌新的日常操作,尝试单引号闭合,可是并没有用,而且因为单引号注入的题太多,导致并没有立刻开始尝试双引号,之后想起双引号(对,双引号木得牌面)得到如下 ...
- numpy 中的堆叠 stack
参考: https://blog.csdn.net/Riverhope/article/details/78922006 vstack,vertical 垂直堆叠 hstack, horizontal ...
- js将秒数转换为时分秒格式
function secondToTimeStr(t) { if (!t) return; if (t < 60) return "00:" + ((i = t) < ...
- 团队作业3_需求改进&系统设计
一.需求&原型改进 1.需求改进: (1)发现问题:通过发布问卷调查及收集整理的形式发现用户的新需求: (2)修改需求:考虑新增提醒用户未完成事件的功能. 附:用户调查问卷(如下) 调研途 ...
- element ui只输入数字校验
注意:圈起来的两个地方,刚开始忘记写type='number'了,导致可以输入'123abc'这样的,之后加上了就OK了