1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
| #include <stdio.h> #include <string.h>
unsigned int SK[32] = { 0xE8DB227C, 0x012451B9, 0xED08A9DB, 0xC91F65C3, 0xB3D1E981, 0x319B4734, 0xA4BA5551, 0xD0F2ED2D, 0x4A00D692, 0xE0AEFE30, 0x6BBCDB4A, 0xC315F6F1, 0xB4E1B030, 0x694C4ACE, 0x479208D3, 0x3F8C7B97, 0x747777A6, 0xEDEC9BBB, 0xC8E506C1, 0xB955A92A, 0xB388FDBB, 0x1A4697C3, 0xB10826AA, 0xBB1F2207, 0x291DCD60, 0x2BA3E3A7, 0x1B83DFDD, 0x014D4FD5, 0x80C659F3, 0x3EB45B23, 0x43E36266, 0xBD22532C };
#define GET_ULONG(n, b, i) \ (n) = ( (unsigned long) (b)[(i + 3)] << 24 ) \ | ( (unsigned long) (b)[(i + 2)] << 16 ) \ | ( (unsigned long) (b)[(i + 1)] << 8 ) \ | ( (unsigned long) (b)[(i )] ); \
#define PUT_ULONG(n, b, i) \ { \ (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ (b)[(i) ] = (unsigned char) ( (n) ); \ }
#define SHL(x, n) ( ((x) & 0xFFFFFFFF) << n )
#define ROTL(x, n) ( SHL((x), n) | ((x) >> (32 - n)) )
#define SWAP(a, b) { unsigned t = a; a = b; b = t; t = 0; }
void SM4_Decrypt(unsigned char * input, unsigned char * output, int len); void Round(unsigned char input[16], unsigned char output[16]);
int main(void) { unsigned char input[] = { 0x7D, 0x54, 0xCB, 0xC0, 0x74, 0xDB, 0xF5, 0xD7, 0x6F, 0xD9, 0x92, 0x1B, 0xEB, 0x28, 0x46, 0x20, 0xE5, 0xD5, 0xD3, 0x60, 0x80, 0x6D, 0x36, 0x2F, 0xB0, 0x63, 0x2F, 0x61, 0x20, 0x0F, 0xA9, 0x30 }; unsigned char output[32] = { 0 }; int i; SM4_Decrypt(input, output, 32); for ( i = 0; i < 32; i++ ) {
printf("%c", output[i]); } return 0; }
void SM4_Decrypt(unsigned char * input, unsigned char * output, int len) { int i; for ( i = 0; i < 16; i++ ) SWAP(SK[i], SK[31 - i]); while ( len > 0 ) { Round(input, output); input += 16; output += 16; len -= 16; } }
void Round(unsigned char input[16], unsigned char output[16]) { unsigned long tmp[4] = { 0 }; int i; unsigned int t = 0; GET_ULONG(tmp[0], input, 0); GET_ULONG(tmp[1], input, 4); GET_ULONG(tmp[2], input, 8); GET_ULONG(tmp[3], input, 12); for ( i = 0; i < 32; i++ ) { t = SK[i] ^ tmp[(i + 1) % 4] ^ tmp[(i + 2) % 4] ^ tmp[(i + 3) % 4]; tmp[i % 4] ^= t ^ ROTL(t, 2) ^ ROTL(t, 24) ^ ROTL(t, 10) ^ ROTL(t, 18); } for ( i = 0 ; i < 4; i++ ) GET_ULONG(SK[26 - i], input, i * 4); PUT_ULONG(tmp[3], output, 0); PUT_ULONG(tmp[2], output, 4); PUT_ULONG(tmp[1], output, 8); PUT_ULONG(tmp[0], output, 12); }
|