国密算法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.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 }
文件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 }
文件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
运行程序
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 阅读(838) 评论(0) 编辑 收藏 举报