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 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
| #include <stdio.h> #include <stdint.h> #include <string.h>
#define SM4_ENCRYPT 1 #define SM4_DECRYPT 0
// SM4 S盒 static const uint8_t Sbox[256] = { 0xD1, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7, 0x16, 0xB6, 0x14, 0xC2, 0x28, 0xFB, 0x2C, 0x05, 0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3, 0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, 0x9C, 0x42, 0x50, 0xF4, 0x91, 0xEF, 0x98, 0x7A, 0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62, 0xE4, 0xB3, 0x17, 0xA9, 0x1C, 0x08, 0xE8, 0x95, 0x80, 0xDF, 0x94, 0xFA, 0x75, 0x8F, 0x3F, 0xA6, 0x47, 0x07, 0xA7, 0x4F, 0xF3, 0x73, 0x71, 0xBA, 0x83, 0x59, 0x3C, 0x19, 0xE6, 0x85, 0xD6, 0xA8, 0x68, 0x6B, 0x81, 0xB2, 0xFC, 0x64, 0xDA, 0x8B, 0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D, 0x35, 0x1E, 0x24, 0x0E, 0x78, 0x63, 0x58, 0x9F, 0xA2, 0x25, 0x22, 0x7C, 0x3B, 0x01, 0x21, 0xC9, 0x87, 0xD4, 0x00, 0x46, 0x57, 0x5E, 0xD3, 0x27, 0x52, 0x4C, 0x36, 0x02, 0xE7, 0xA0, 0xC4, 0xC8, 0x9E, 0xEA, 0xBF, 0x8A, 0xD2, 0x40, 0xC7, 0x38, 0xB5, 0xA3, 0xF7, 0xF2, 0xCE, 0xF9, 0x61, 0x15, 0xA1, 0xE0, 0xAE, 0x5D, 0xA4, 0x9B, 0x34, 0x1A, 0x55, 0xAD, 0x93, 0x32, 0x30, 0xF5, 0x8C, 0xB1, 0xE3, 0x1D, 0xF6, 0xE2, 0x2E, 0x82, 0x66, 0xCA, 0x60, 0xC0, 0x29, 0x23, 0xAB, 0x0D, 0x53, 0x4E, 0x6F, 0xD5, 0xDB, 0x37, 0x45, 0xDE, 0xFD, 0x8E, 0x2F, 0x03, 0xFF, 0x6A, 0x72, 0x6D, 0x6C, 0x5B, 0x51, 0x8D, 0x1B, 0xAF, 0x92, 0xBB, 0xDD, 0xBC, 0x7F, 0x11, 0xD9, 0x5C, 0x41, 0x1F, 0x10, 0x5A, 0xD8, 0x0A, 0xC1, 0x31, 0x88, 0xA5, 0xCD, 0x7B, 0xBD, 0x2D, 0x74, 0xD0, 0x12, 0xB8, 0xE5, 0xB4, 0xB0, 0x89, 0x69, 0x97, 0x4A, 0x0C, 0x96, 0x77, 0x7E, 0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84, 0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D, 0x20, 0x79, 0xEE, 0x5F, 0x3E, 0xD7, 0xCB, 0x39, 0x48 };
// 系统参数 FK static const uint32_t FK[4] = { 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc };
// 固定参数 CK static const uint32_t CK[32] = { 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 };
// 循环左移函数 uint32_t rotl(uint32_t x, int n) { return (x << n) | (x >> (32 - n)); }
// 非线性变换 τ(S盒替换) uint32_t tau(uint32_t A) { uint32_t a0 = (A >> 24) & 0xff; uint32_t a1 = (A >> 16) & 0xff; uint32_t a2 = (A >> 8) & 0xff; uint32_t a3 = A & 0xff; uint32_t b0 = Sbox[a0]; uint32_t b1 = Sbox[a1]; uint32_t b2 = Sbox[a2]; uint32_t b3 = Sbox[a3]; return (b0 << 24) | (b1 << 16) | (b2 << 8) | b3; }
// 线性变换 L(用于加密/解密轮函数) uint32_t L(uint32_t B) { return B ^ rotl(B, 2) ^ rotl(B, 10) ^ rotl(B, 18) ^ rotl(B, 24); }
// 线性变换 L'(用于密钥扩展) uint32_t L_prime(uint32_t B) { return B ^ rotl(B, 13) ^ rotl(B, 23); }
// 密钥扩展,生成32个轮密钥 void sm4_key_schedule(const uint8_t key[16], uint32_t rk[32]) { uint32_t K[36]; int i; // 将用户密钥转换为 32 位整数,并与 FK 异或 for (i = 0; i < 4; i++) { K[i] = ((uint32_t)key[4*i] << 24) | ((uint32_t)key[4*i+1] << 16) | ((uint32_t)key[4*i+2] << 8) | ((uint32_t)key[4*i+3]); K[i] ^= FK[i]; } // 生成32个轮密钥 for (i = 0; i < 32; i++) { uint32_t temp = K[i+1] ^ K[i+2] ^ K[i+3] ^ CK[i]; temp = tau(temp); temp = L_prime(temp); K[i+4] = K[i] ^ temp; rk[i] = K[i+4]; } }
// SM4 单轮加密/解密操作 void sm4_crypt(const uint8_t in[16], uint8_t out[16], const uint32_t rk[32]) { uint32_t X[36]; int i; // 将输入明文(或密文)分成4个 32 位字 for (i = 0; i < 4; i++) { X[i] = ((uint32_t)in[4*i] << 24) | ((uint32_t)in[4*i+1] << 16) | ((uint32_t)in[4*i+2] << 8) | ((uint32_t)in[4*i+3]); } // 进行32轮迭代 for (i = 0; i < 32; i++) { uint32_t temp = X[i+1] ^ X[i+2] ^ X[i+3] ^ rk[i]; temp = tau(temp); temp = L(temp); X[i+4] = X[i] ^ temp; } // 结果为 X35, X34, X33, X32(倒序输出) for (i = 0; i < 4; i++) { uint32_t x = X[35 - i]; out[4*i] = (uint8_t)(x >> 24); out[4*i+1] = (uint8_t)(x >> 16); out[4*i+2] = (uint8_t)(x >> 8); out[4*i+3] = (uint8_t)(x); } }
int main() { // 示例密钥(16字节) uint8_t key[16] = { 0x4E, 0x43, 0x54, 0x46, 0x32, 0x34, 0x6E, 0x63, 0x74, 0x66, 0x4E, 0x43, 0x54, 0x46, 0x32, 0x34 };
// 示例密文(16字节),请将此处替换为实际密文 uint8_t ciphertext[16] = { 0x14, 0x5B, 0xA6, 0x2A, 0xA8, 0x05, 0xA5, 0xF3, 0x76, 0xBE, 0xC9, 0x01, 0xF9, 0x36, 0x7B, 0x46 };
uint8_t plaintext[16]; uint32_t rk[32];
// 生成轮密钥 sm4_key_schedule(key, rk);
// 解密时需要将轮密钥逆序使用 uint32_t rk_dec[32]; for (int i = 0; i < 32; i++) { rk_dec[i] = rk[31 - i]; }
// 进行解密运算 sm4_crypt(ciphertext, plaintext, rk_dec);
// 输出解密后的明文 for (int i = 0; i < 16; i++) { printf("%02x ", plaintext[i]); } printf("\n");
return 0; }
|