国密算法SM4 - 对称

1.SM4使用了Fesitel结构来加密和解密

 

2.对称密码需要和迭代结合使用

 

3.源码实现(参考了openssl)

文件结构

文件sm4.h

 1 #ifndef OSSL_CRYPTO_SM4_H
 2 # define OSSL_CRYPTO_SM4_H
 3 
 4 # ifdef OPENSSL_NO_SM4
 5 #  error SM4 is disabled.
 6 # endif
 7 
 8 # define SM4_ENCRYPT     1
 9 # define SM4_DECRYPT     0
10 
11 # define SM4_BLOCK_SIZE    16
12 # define SM4_KEY_SCHEDULE  32
13 
14 #include <stdint.h>
15 
16 typedef struct SM4_KEY_st {
17     uint32_t rk[SM4_KEY_SCHEDULE];
18 } SM4_KEY;
19 
20 int SM4_set_key(const uint8_t *key, SM4_KEY *ks);
21 
22 void SM4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks);
23 
24 void SM4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks);
25 
26 
27 #endif
sm4.h

文件sm4.c

  1 #include "sm4.h"
  2 
  3 static const uint8_t SM4_S[256] = {
  4     0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7, 0x16, 0xB6, 0x14, 0xC2,
  5     0x28, 0xFB, 0x2C, 0x05, 0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3,
  6     0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, 0x9C, 0x42, 0x50, 0xF4,
  7     0x91, 0xEF, 0x98, 0x7A, 0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62,
  8     0xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95, 0x80, 0xDF, 0x94, 0xFA,
  9     0x75, 0x8F, 0x3F, 0xA6, 0x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA,
 10     0x83, 0x59, 0x3C, 0x19, 0xE6, 0x85, 0x4F, 0xA8, 0x68, 0x6B, 0x81, 0xB2,
 11     0x71, 0x64, 0xDA, 0x8B, 0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D, 0x35,
 12     0x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2, 0x25, 0x22, 0x7C, 0x3B,
 13     0x01, 0x21, 0x78, 0x87, 0xD4, 0x00, 0x46, 0x57, 0x9F, 0xD3, 0x27, 0x52,
 14     0x4C, 0x36, 0x02, 0xE7, 0xA0, 0xC4, 0xC8, 0x9E, 0xEA, 0xBF, 0x8A, 0xD2,
 15     0x40, 0xC7, 0x38, 0xB5, 0xA3, 0xF7, 0xF2, 0xCE, 0xF9, 0x61, 0x15, 0xA1,
 16     0xE0, 0xAE, 0x5D, 0xA4, 0x9B, 0x34, 0x1A, 0x55, 0xAD, 0x93, 0x32, 0x30,
 17     0xF5, 0x8C, 0xB1, 0xE3, 0x1D, 0xF6, 0xE2, 0x2E, 0x82, 0x66, 0xCA, 0x60,
 18     0xC0, 0x29, 0x23, 0xAB, 0x0D, 0x53, 0x4E, 0x6F, 0xD5, 0xDB, 0x37, 0x45,
 19     0xDE, 0xFD, 0x8E, 0x2F, 0x03, 0xFF, 0x6A, 0x72, 0x6D, 0x6C, 0x5B, 0x51,
 20     0x8D, 0x1B, 0xAF, 0x92, 0xBB, 0xDD, 0xBC, 0x7F, 0x11, 0xD9, 0x5C, 0x41,
 21     0x1F, 0x10, 0x5A, 0xD8, 0x0A, 0xC1, 0x31, 0x88, 0xA5, 0xCD, 0x7B, 0xBD,
 22     0x2D, 0x74, 0xD0, 0x12, 0xB8, 0xE5, 0xB4, 0xB0, 0x89, 0x69, 0x97, 0x4A,
 23     0x0C, 0x96, 0x77, 0x7E, 0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84,
 24     0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D, 0x20, 0x79, 0xEE, 0x5F, 0x3E,
 25     0xD7, 0xCB, 0x39, 0x48
 26 };
 27 
 28 static const uint32_t SM4_SBOX_T[256] = {
 29     0x8ED55B5B, 0xD0924242, 0x4DEAA7A7, 0x06FDFBFB, 0xFCCF3333, 0x65E28787,
 30     0xC93DF4F4, 0x6BB5DEDE, 0x4E165858, 0x6EB4DADA, 0x44145050, 0xCAC10B0B,
 31     0x8828A0A0, 0x17F8EFEF, 0x9C2CB0B0, 0x11051414, 0x872BACAC, 0xFB669D9D,
 32     0xF2986A6A, 0xAE77D9D9, 0x822AA8A8, 0x46BCFAFA, 0x14041010, 0xCFC00F0F,
 33     0x02A8AAAA, 0x54451111, 0x5F134C4C, 0xBE269898, 0x6D482525, 0x9E841A1A,
 34     0x1E061818, 0xFD9B6666, 0xEC9E7272, 0x4A430909, 0x10514141, 0x24F7D3D3,
 35     0xD5934646, 0x53ECBFBF, 0xF89A6262, 0x927BE9E9, 0xFF33CCCC, 0x04555151,
 36     0x270B2C2C, 0x4F420D0D, 0x59EEB7B7, 0xF3CC3F3F, 0x1CAEB2B2, 0xEA638989,
 37     0x74E79393, 0x7FB1CECE, 0x6C1C7070, 0x0DABA6A6, 0xEDCA2727, 0x28082020,
 38     0x48EBA3A3, 0xC1975656, 0x80820202, 0xA3DC7F7F, 0xC4965252, 0x12F9EBEB,
 39     0xA174D5D5, 0xB38D3E3E, 0xC33FFCFC, 0x3EA49A9A, 0x5B461D1D, 0x1B071C1C,
 40     0x3BA59E9E, 0x0CFFF3F3, 0x3FF0CFCF, 0xBF72CDCD, 0x4B175C5C, 0x52B8EAEA,
 41     0x8F810E0E, 0x3D586565, 0xCC3CF0F0, 0x7D196464, 0x7EE59B9B, 0x91871616,
 42     0x734E3D3D, 0x08AAA2A2, 0xC869A1A1, 0xC76AADAD, 0x85830606, 0x7AB0CACA,
 43     0xB570C5C5, 0xF4659191, 0xB2D96B6B, 0xA7892E2E, 0x18FBE3E3, 0x47E8AFAF,
 44     0x330F3C3C, 0x674A2D2D, 0xB071C1C1, 0x0E575959, 0xE99F7676, 0xE135D4D4,
 45     0x661E7878, 0xB4249090, 0x360E3838, 0x265F7979, 0xEF628D8D, 0x38596161,
 46     0x95D24747, 0x2AA08A8A, 0xB1259494, 0xAA228888, 0x8C7DF1F1, 0xD73BECEC,
 47     0x05010404, 0xA5218484, 0x9879E1E1, 0x9B851E1E, 0x84D75353, 0x00000000,
 48     0x5E471919, 0x0B565D5D, 0xE39D7E7E, 0x9FD04F4F, 0xBB279C9C, 0x1A534949,
 49     0x7C4D3131, 0xEE36D8D8, 0x0A020808, 0x7BE49F9F, 0x20A28282, 0xD4C71313,
 50     0xE8CB2323, 0xE69C7A7A, 0x42E9ABAB, 0x43BDFEFE, 0xA2882A2A, 0x9AD14B4B,
 51     0x40410101, 0xDBC41F1F, 0xD838E0E0, 0x61B7D6D6, 0x2FA18E8E, 0x2BF4DFDF,
 52     0x3AF1CBCB, 0xF6CD3B3B, 0x1DFAE7E7, 0xE5608585, 0x41155454, 0x25A38686,
 53     0x60E38383, 0x16ACBABA, 0x295C7575, 0x34A69292, 0xF7996E6E, 0xE434D0D0,
 54     0x721A6868, 0x01545555, 0x19AFB6B6, 0xDF914E4E, 0xFA32C8C8, 0xF030C0C0,
 55     0x21F6D7D7, 0xBC8E3232, 0x75B3C6C6, 0x6FE08F8F, 0x691D7474, 0x2EF5DBDB,
 56     0x6AE18B8B, 0x962EB8B8, 0x8A800A0A, 0xFE679999, 0xE2C92B2B, 0xE0618181,
 57     0xC0C30303, 0x8D29A4A4, 0xAF238C8C, 0x07A9AEAE, 0x390D3434, 0x1F524D4D,
 58     0x764F3939, 0xD36EBDBD, 0x81D65757, 0xB7D86F6F, 0xEB37DCDC, 0x51441515,
 59     0xA6DD7B7B, 0x09FEF7F7, 0xB68C3A3A, 0x932FBCBC, 0x0F030C0C, 0x03FCFFFF,
 60     0xC26BA9A9, 0xBA73C9C9, 0xD96CB5B5, 0xDC6DB1B1, 0x375A6D6D, 0x15504545,
 61     0xB98F3636, 0x771B6C6C, 0x13ADBEBE, 0xDA904A4A, 0x57B9EEEE, 0xA9DE7777,
 62     0x4CBEF2F2, 0x837EFDFD, 0x55114444, 0xBDDA6767, 0x2C5D7171, 0x45400505,
 63     0x631F7C7C, 0x50104040, 0x325B6969, 0xB8DB6363, 0x220A2828, 0xC5C20707,
 64     0xF531C4C4, 0xA88A2222, 0x31A79696, 0xF9CE3737, 0x977AEDED, 0x49BFF6F6,
 65     0x992DB4B4, 0xA475D1D1, 0x90D34343, 0x5A124848, 0x58BAE2E2, 0x71E69797,
 66     0x64B6D2D2, 0x70B2C2C2, 0xAD8B2626, 0xCD68A5A5, 0xCB955E5E, 0x624B2929,
 67     0x3C0C3030, 0xCE945A5A, 0xAB76DDDD, 0x867FF9F9, 0xF1649595, 0x5DBBE6E6,
 68     0x35F2C7C7, 0x2D092424, 0xD1C61717, 0xD66FB9B9, 0xDEC51B1B, 0x94861212,
 69     0x78186060, 0x30F3C3C3, 0x897CF5F5, 0x5CEFB3B3, 0xD23AE8E8, 0xACDF7373,
 70     0x794C3535, 0xA0208080, 0x9D78E5E5, 0x56EDBBBB, 0x235E7D7D, 0xC63EF8F8,
 71     0x8BD45F5F, 0xE7C82F2F, 0xDD39E4E4, 0x68492121 };
 72 
 73 
 74 static inline uint32_t rotl(uint32_t a, uint8_t n)
 75 {
 76     return (a << n) | (a >> (32 - n));
 77 }
 78 
 79 static inline uint32_t load_u32_be(const uint8_t *b, uint32_t n)
 80 {
 81     return ((uint32_t)b[4 * n] << 24) |
 82            ((uint32_t)b[4 * n + 1] << 16) |
 83            ((uint32_t)b[4 * n + 2] << 8) |
 84            ((uint32_t)b[4 * n + 3]);
 85 }
 86 
 87 static inline void store_u32_be(uint32_t v, uint8_t *b)
 88 {
 89     b[0] = (uint8_t)(v >> 24);
 90     b[1] = (uint8_t)(v >> 16);
 91     b[2] = (uint8_t)(v >> 8);
 92     b[3] = (uint8_t)(v);
 93 }
 94 
 95 static inline uint32_t SM4_T_slow(uint32_t X)
 96 {
 97     uint32_t t = 0;
 98 
 99     t |= ((uint32_t)SM4_S[(uint8_t)(X >> 24)]) << 24;
100     t |= ((uint32_t)SM4_S[(uint8_t)(X >> 16)]) << 16;
101     t |= ((uint32_t)SM4_S[(uint8_t)(X >> 8)]) << 8;
102     t |= SM4_S[(uint8_t)X];
103 
104     /*
105      * L linear transform
106      */
107     return t ^ rotl(t, 2) ^ rotl(t, 10) ^ rotl(t, 18) ^ rotl(t, 24);
108 }
109 
110 static inline uint32_t SM4_T(uint32_t X)
111 {
112     return SM4_SBOX_T[(uint8_t)(X >> 24)] ^
113            rotl(SM4_SBOX_T[(uint8_t)(X >> 16)], 24) ^
114            rotl(SM4_SBOX_T[(uint8_t)(X >> 8)], 16) ^
115            rotl(SM4_SBOX_T[(uint8_t)X], 8);
116 }
117 
118 int SM4_set_key(const uint8_t *key, SM4_KEY *ks)
119 {
120     /*
121      * Family Key
122      */
123     static const uint32_t FK[4] =
124         { 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc };
125 
126     /*
127      * Constant Key
128      */
129     static const uint32_t CK[32] = {
130         0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269,
131         0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9,
132         0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249,
133         0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9,
134         0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229,
135         0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299,
136         0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209,
137         0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279
138     };
139 
140     uint32_t K[4];
141     int i;
142 
143     K[0] = load_u32_be(key, 0) ^ FK[0];
144     K[1] = load_u32_be(key, 1) ^ FK[1];
145     K[2] = load_u32_be(key, 2) ^ FK[2];
146     K[3] = load_u32_be(key, 3) ^ FK[3];
147 
148     for (i = 0; i != SM4_KEY_SCHEDULE; ++i) {
149         uint32_t X = K[(i + 1) % 4] ^ K[(i + 2) % 4] ^ K[(i + 3) % 4] ^ CK[i];
150         uint32_t t = 0;
151 
152         t |= ((uint32_t)SM4_S[(uint8_t)(X >> 24)]) << 24;
153         t |= ((uint32_t)SM4_S[(uint8_t)(X >> 16)]) << 16;
154         t |= ((uint32_t)SM4_S[(uint8_t)(X >> 8)]) << 8;
155         t |= SM4_S[(uint8_t)X];
156 
157         t = t ^ rotl(t, 13) ^ rotl(t, 23);
158         K[i % 4] ^= t;
159         ks->rk[i] = K[i % 4];
160     }
161 
162     return 1;
163 }
164 
165 #define SM4_RNDS(k0, k1, k2, k3, F)          \
166       do {                                   \
167          B0 ^= F(B1 ^ B2 ^ B3 ^ ks->rk[k0]); \
168          B1 ^= F(B0 ^ B2 ^ B3 ^ ks->rk[k1]); \
169          B2 ^= F(B0 ^ B1 ^ B3 ^ ks->rk[k2]); \
170          B3 ^= F(B0 ^ B1 ^ B2 ^ ks->rk[k3]); \
171       } while(0)
172 
173 void SM4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks)
174 {
175     uint32_t B0 = load_u32_be(in, 0);
176     uint32_t B1 = load_u32_be(in, 1);
177     uint32_t B2 = load_u32_be(in, 2);
178     uint32_t B3 = load_u32_be(in, 3);
179 
180     /*
181      * Uses byte-wise sbox in the first and last rounds to provide some
182      * protection from cache based side channels.
183      */
184     SM4_RNDS( 0,  1,  2,  3, SM4_T_slow);
185     SM4_RNDS( 4,  5,  6,  7, SM4_T);
186     SM4_RNDS( 8,  9, 10, 11, SM4_T);
187     SM4_RNDS(12, 13, 14, 15, SM4_T);
188     SM4_RNDS(16, 17, 18, 19, SM4_T);
189     SM4_RNDS(20, 21, 22, 23, SM4_T);
190     SM4_RNDS(24, 25, 26, 27, SM4_T);
191     SM4_RNDS(28, 29, 30, 31, SM4_T_slow);
192 
193     store_u32_be(B3, out);
194     store_u32_be(B2, out + 4);
195     store_u32_be(B1, out + 8);
196     store_u32_be(B0, out + 12);
197 }
198 
199 void SM4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks)
200 {
201     uint32_t B0 = load_u32_be(in, 0);
202     uint32_t B1 = load_u32_be(in, 1);
203     uint32_t B2 = load_u32_be(in, 2);
204     uint32_t B3 = load_u32_be(in, 3);
205 
206     SM4_RNDS(31, 30, 29, 28, SM4_T_slow);
207     SM4_RNDS(27, 26, 25, 24, SM4_T);
208     SM4_RNDS(23, 22, 21, 20, SM4_T);
209     SM4_RNDS(19, 18, 17, 16, SM4_T);
210     SM4_RNDS(15, 14, 13, 12, SM4_T);
211     SM4_RNDS(11, 10,  9,  8, SM4_T);
212     SM4_RNDS( 7,  6,  5,  4, SM4_T);
213     SM4_RNDS( 3,  2,  1,  0, SM4_T_slow);
214 
215     store_u32_be(B3, out);
216     store_u32_be(B2, out + 4);
217     store_u32_be(B1, out + 8);
218     store_u32_be(B0, out + 12);
219 }
sm4.c

文件main.c

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 #include "sm4.h"
 5 void log_hex(uint8_t *data, size_t ndata, uint8_t *description){
 6     printf("%s: ", description);
 7     size_t i = 0;
 8     for(i=0; i<ndata; i++){
 9         printf("%02x ", data[i]);
10     }
11     printf("\n");
12 }
13 
14 static int test_sm4(){
15     uint8_t k[SM4_BLOCK_SIZE] = {
16             0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
17             0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10
18     };
19     uint8_t input[SM4_BLOCK_SIZE] = {
20             0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
21             0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10
22         };
23     int i;
24     SM4_KEY key;
25     SM4_set_key(k, &key);
26 
27     uint8_t block[SM4_BLOCK_SIZE];
28     SM4_encrypt(input, block, &key);
29     for(i=0; i != 999999; ++i){
30         SM4_encrypt(block, block, &key);
31     }
32 
33     printf("本部分为SM4分组密码算法,对一组明文反复加密1 000 000次的运算:\n");
34     log_hex(k, SM4_BLOCK_SIZE, "输入密钥");
35     log_hex(input, SM4_BLOCK_SIZE, "输入明文");
36 
37     log_hex(block, SM4_BLOCK_SIZE, "输出密文");
38     return 0;
39 }
40 
41 int main(){
42     return test_sm4();
43 }
main.c

文件Makefile

1 all:
2     gcc -c sm4.c -o sm4.o 
3     gcc -c main.c -o main.o
4     gcc -o bin sm4.o main.o
Makefile


运行程序

 

4.参考文献

1.《图解密码技术》 2015 (日)结城浩(著)
2.《密码编码学与网络安全—原理与实践 第五版》 3.1.3 Feistel密码, 11.5.1 SHA-512逻辑

3.《GM T 0002-2012 SM4分组密码算法.pdf

4.点击

http://www.gmbz.org.cn/main/index.html

进入"标准查询入口"

或者,直接进入 http://www.gmbz.org.cn/main/bzlb.html

 

posted on 2020-12-22 19:06  LiveWithACat  阅读(714)  评论(0编辑  收藏  举报