└── sm ├── SM3.py ├── SM4.py ├── __init__.py ├── common.py └── common.pyc /sm/SM3.py: -------------------------------------------------------------------------------- 1 | # -*-coding:utf-8-*- 2 | ''' 3 | Created on 2016-4-7 4 | 5 | @author: 014731 6 | ''' 7 | 8 | from common import * 9 | ''' 10 | IV:初始值,用于确定压缩函数寄存器的初态 11 | ''' 12 | IV = (0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e) 13 | 14 | ''' 15 | T(j):常量,随j的变化取不同的值 16 | ''' 17 | T0_15 = 0x79cc4519 18 | T16_63= 0x7a879d8a 19 | 20 | ''' 21 | SM3支持的消息最大比特长度 22 | ''' 23 | SM3_MSG_MAX_BITS = 2 << 63 24 | 25 | ''' 26 | FF(j):布尔函数,随j的变化取不同的表达式 27 | GG(j):布尔函数,随j的变化取不同的表达式 28 | ''' 29 | def _ff_0_15(x, y, z): 30 | ''' 31 | FF(j):布尔函数 0<=j<=15 32 | ''' 33 | if is_word(x) == False: 34 | raise Exception('源数据[%X]不在word定义范围[0x00000000 - 0xFFFFFFFF],不能进行变换计算' % x) 35 | if is_word(y) == False: 36 | raise Exception('源数据[%X]不在word定义范围[0x00000000 - 0xFFFFFFFF],不能进行变换计算' % y) 37 | if is_word(z) == False: 38 | raise Exception('源数据[%X]不在word定义范围[0x00000000 - 0xFFFFFFFF],不能进行变换计算' % z) 39 | 40 | return x ^ y ^ z 41 | 42 | def _ff_16_63(x, y, z): 43 | ''' 44 | FF(j):布尔函数 16<=j<=63 45 | ''' 46 | if is_word(x) == False: 47 | raise Exception('源数据[%X]不在word定义范围[0x00000000 - 0xFFFFFFFF],不能进行变换计算' % x) 48 | if is_word(y) == False: 49 | raise Exception('源数据[%X]不在word定义范围[0x00000000 - 0xFFFFFFFF],不能进行变换计算' % y) 50 | if is_word(z) == False: 51 | raise Exception('源数据[%X]不在word定义范围[0x00000000 - 0xFFFFFFFF],不能进行变换计算' % z) 52 | 53 | return (x & y)|(x & z)|(y & z) 54 | 55 | def _gg_0_15(x, y, z): 56 | ''' 57 | GG(j):布尔函数 0<=j<=15 58 | ''' 59 | if is_word(x) == False: 60 | raise Exception('源数据[%X]不在word定义范围[0x00000000 - 0xFFFFFFFF],不能进行变换计算' % x) 61 | if is_word(y) == False: 62 | raise Exception('源数据[%X]不在word定义范围[0x00000000 - 0xFFFFFFFF],不能进行变换计算' % y) 63 | if is_word(z) == False: 64 | raise Exception('源数据[%X]不在word定义范围[0x00000000 - 0xFFFFFFFF],不能进行变换计算' % z) 65 | 66 | return x ^ y ^ z 67 | 68 | def _gg_16_63(x, y, z): 69 | ''' 70 | GG(j):布尔函数 16<=j<=63 71 | ''' 72 | if is_word(x) == False: 73 | raise Exception('源数据[%X]不在word定义范围[0x00000000 - 0xFFFFFFFF],不能进行变换计算' % x) 74 | if is_word(y) == False: 75 | raise Exception('源数据[%X]不在word定义范围[0x00000000 - 0xFFFFFFFF],不能进行变换计算' % y) 76 | if is_word(z) == False: 77 | raise Exception('源数据[%X]不在word定义范围[0x00000000 - 0xFFFFFFFF],不能进行变换计算' % z) 78 | 79 | return (x & y)|((~x) & z) 80 | 81 | 82 | def _p0_conv(x): 83 | ''' 84 | P0:压缩函数中的置换函数 85 | ''' 86 | if is_word(x) == False: 87 | raise Exception('源数据[%X]不在word定义范围[0x00000000 - 0xFFFFFFFF],不能进行变换计算' % x) 88 | 89 | return x ^ lrotate(x, 9) ^ lrotate(x, 17) 90 | 91 | def _p1_conv(x): 92 | ''' 93 | P1:压缩函数中的置换函数 94 | ''' 95 | if is_word(x) == False: 96 | raise Exception('源数据[%X]不在word定义范围[0x00000000 - 0xFFFFFFFF],不能进行变换计算' % x) 97 | 98 | return x ^ lrotate(x, 15) ^ lrotate(x, 23) 99 | 100 | def _sm3_message_pad(message): 101 | ''' 102 | 假设消息m 的长度为L比特。首先将比特'1'添加到消息的末尾,再添加k 个'0',k是满 103 | 足L + 1 + k与448 mod 512 同余((L+1+k) mod 512 = 448 % 512) 的最小的非负整数。然后再添加一个64位比特串,该比特串是长度L的二进 104 | 制表示。填充后的消息m′的比特长度为512的倍数。 105 | ''' 106 | if len(message) % 2 != 0: 107 | raise Exception('待填充数据长度[%s]错误,需要为2的整倍数' % len(message)) 108 | 109 | if IsHexCharacter(message) == False: 110 | raise Exception('待填充数据含有非法字符(非16进制字符)') 111 | 112 | len_bits = len(message) * 4 113 | ''' 114 | 搜寻k值 115 | ''' 116 | k = 7 117 | while True: 118 | if (len_bits + 1 + k) % 512 == 448 % 512: 119 | break 120 | else: 121 | k += 8 122 | ''' 123 | 填充1个'1',再填充k个'0' 124 | ''' 125 | padmsg = message + '80' 126 | out_format = '%%0%dX' % ((k-7)/4) 127 | padmsg += out_format % 0x00 128 | 129 | ''' 130 | 填充长度 131 | ''' 132 | padmsg += '%016X' % len_bits 133 | 134 | if (len(padmsg) * 4) % 512 != 0: 135 | raise Exception('填充后数据长度[%d]错误, 必须为512整数倍' % len(padmsg)) 136 | 137 | return (padmsg, len(padmsg) * 4) 138 | 139 | class SM3(object): 140 | ''' 141 | SM3密码杂凑算法 142 | ''' 143 | def __init__(self, srcmsg = '00'): 144 | self.message, self.length = _sm3_message_pad(srcmsg) 145 | 146 | def __str__(self): 147 | return 'SM3 object :\nmessage : %s\nlength : %d bits\n' % (self.message, self.length) 148 | 149 | def _cf_process(self, iv, message_group): 150 | ''' 151 | CF压缩函数 152 | iv : int 153 | message_group : hexstring 154 | ''' 155 | try: 156 | W, WE = self._message_extend(message_group) 157 | except Exception, e: 158 | raise Exception(e) 159 | ''' 160 | for num in W: 161 | print '%08X' % num 162 | for num in WE: 163 | print '%08X' % num 164 | ''' 165 | A = iv[0] 166 | B = iv[1] 167 | C = iv[2] 168 | D = iv[3] 169 | E = iv[4] 170 | F = iv[5] 171 | G = iv[6] 172 | H = iv[7] 173 | 174 | print '迭代压缩中间值:\n j A B C D E F G H ' 175 | print 'iv %08X %08X %08X %08X %08X %08X %08X %08X' % (A,B,C,D,E,F,G,H) 176 | 177 | for i in xrange(0, 63 + 1): 178 | if 0 <= i <= 15: 179 | SS1 = lrotate((lrotate(A, 12) + E + lrotate(T0_15, i))%(2<<31), 7) 180 | else: 181 | if i <= 32: 182 | SS1 = lrotate((lrotate(A, 12) + E + lrotate(T16_63, i))%(2<<31), 7) 183 | else: 184 | SS1 = lrotate((lrotate(A, 12) + E + lrotate(T16_63, abs(32 - i)))%(2<<31), 7) 185 | 186 | SS2 = SS1 ^ lrotate(A, 12) 187 | 188 | if 0 <= i <= 15: 189 | TT1 = (_ff_0_15(A, B, C) + D + SS2 + WE[i])%(2<<31) 190 | TT2 = (_gg_0_15(E, F, G) + H + SS1 + W[i])%(2<<31) 191 | else: 192 | if i == 16: 193 | pass 194 | TT1 = (_ff_16_63(A, B, C) + D + SS2 + WE[i])%(2<<31) 195 | TT2 = (_gg_16_63(E, F, G) + H + SS1 + W[i])%(2<<31) 196 | 197 | D = C 198 | C = lrotate(B, 9) 199 | B = A 200 | A = TT1 201 | H = G 202 | G = lrotate(F, 19) 203 | F = E 204 | E = _p0_conv(TT2) 205 | print '%02d %08X %08X %08X %08X %08X %08X %08X %08X' % (i, A,B,C,D,E,F,G,H) 206 | 207 | return (A^iv[0], B^iv[1], C^iv[2], D^iv[3], E^iv[4], F^iv[5], G^iv[6], H^iv[7]) 208 | 209 | def _message_extend(self, message_group): 210 | ''' 211 | W(j)生成, 消息扩展, 返回 (W, WE) 212 | ''' 213 | if IsHexCharacter(message_group) == False: 214 | raise Exception('分组消息含有非法字符(非16进制字符)') 215 | 216 | if len(message_group) % 16 != 0: 217 | raise Exception('用于扩展的分组消息长度[%d]错误' % len(message_group)) 218 | 219 | W = [] 220 | WE = [] 221 | ''' 222 | W0 - W15 223 | ''' 224 | position = 0 225 | while True: 226 | W.append(int(message_group[position:position + 8], 16)) 227 | position += 8 228 | if len(message_group) == position: 229 | break 230 | 231 | ''' 232 | W16 - W67 233 | ''' 234 | for i in xrange(16, 67 + 1): 235 | rspP1 = _p1_conv(W[i - 16] ^ W[i - 9] ^ lrotate(W[i - 3], 15)) 236 | W.append(rspP1 ^ lrotate(W[i - 13], 7) ^ W[i - 6]) 237 | 238 | ''' 239 | WE0 - WE63 240 | ''' 241 | for i in xrange(0, 63 + 1): 242 | WE.append(W[i] ^ W[i+4]) 243 | 244 | return (W, WE) 245 | 246 | def sm3_hash(self): 247 | ''' 248 | SM3 计算杂凑值 249 | ''' 250 | n = self.length / 512 251 | position = 0 252 | v = [] 253 | v.append(IV) 254 | for i in xrange(0, n): 255 | v.append(self._cf_process(v[i], self.message[position: position + 128])) 256 | 257 | position += 128 258 | if len(self.message) == position: 259 | break 260 | return '%08X%08X%08X%08X%08X%08X%08X%08X' % (v[len(v)-1]) 261 | 262 | #--------------------------------------------------------------------------------------------- 263 | if __name__ == '__main__': 264 | message = 'ab' 265 | sm3 = SM3(message) 266 | print sm3.__str__() 267 | print '\nHASH: %s' % sm3.sm3_hash() 268 | print '-'*120 269 | message = '04D24163C411A9D03A3B77A082B29064CAD7A3FA737C13667D6F67760D9C86A984A0A1DDEAFD0A8C4B5F7223EA64D5CFB70BD29F4AC33FB343069DC4E499E8D354649444570F02F46319B5927DE7E09210FEEFDA4D5847BC4204B159D45517040B1C6A' 270 | sm3 = SM3(message) 271 | print sm3.__str__() 272 | print '\nHASH: %s' % sm3.sm3_hash() 273 | print '-'*120 -------------------------------------------------------------------------------- /sm/SM4.py: -------------------------------------------------------------------------------- 1 | # -*-coding:utf-8-*- 2 | ''' 3 | Created on 2016-4-6 4 | 5 | @author: 014731 6 | ''' 7 | 8 | import common 9 | 10 | ''' 11 | FK=(FK0, FK1, FK2, FK3)为系统参数,CK=(CK0, CK1,…, CK31)为固定参数, 12 | 用于密钥扩展算法,其中FKi(i=0,…,3)、CKi(i=0,…,31)为字。 13 | FK与CK值由国家密码算法规范指定 14 | ''' 15 | SM4_FK = (0xA3B1BAC6, 0x56AA3350, 0x677D9197, 0xB27022DC) 16 | SM4_CK = (0X00070E15, 0X1C232A31, 0X383F464D, 0X545B6269, 17 | 0X70777E85, 0X8C939AA1, 0XA8AFB6BD, 0XC4CBD2D9, 18 | 0XE0E7EEF5, 0XFC030A11, 0X181F262D, 0X343B4249, 19 | 0X50575E65, 0X6C737A81, 0X888F969D, 0XA4ABB2B9, 20 | 0XC0C7CED5, 0XDCE3EAF1, 0XF8FF060D, 0X141B2229, 21 | 0X30373E45, 0X4C535A61, 0X686F767D, 0X848B9299, 22 | 0XA0A7AEB5, 0XBCC3CAD1, 0XD8DFE6ED, 0XF4FB0209, 23 | 0X10171E25, 0X2C333A41, 0X484F565D, 0X646B7279) 24 | ''' 25 | S 盒为固定的 8 比特输入 8 比特输出的置换,记为 Sbox(.) 26 | S盒阵列值由国家密码算法规范指定 27 | ''' 28 | SM4_SBOX = [0XD6, 0X90, 0XE9, 0XFE, 0XCC, 0XE1, 0X3D, 0XB7, 0X16, 0XB6, 0X14, 0XC2, 0X28, 0XFB, 0X2C, 0X05, 29 | 0X2B, 0X67, 0X9A, 0X76, 0X2A, 0XBE, 0X04, 0XC3, 0XAA, 0X44, 0X13, 0X26, 0X49, 0X86, 0X06, 0X99, 30 | 0X9C, 0X42, 0X50, 0XF4, 0X91, 0XEF, 0X98, 0X7A, 0X33, 0X54, 0X0B, 0X43, 0XED, 0XCF, 0XAC, 0X62, 31 | 0XE4, 0XB3, 0X1C, 0XA9, 0XC9, 0X08, 0XE8, 0X95, 0X80, 0XDF, 0X94, 0XFA, 0X75, 0X8F, 0X3F, 0XA6, 32 | 0X47, 0X07, 0XA7, 0XFC, 0XF3, 0X73, 0X17, 0XBA, 0X83, 0X59, 0X3C, 0X19, 0XE6, 0X85, 0X4F, 0XA8, 33 | 0X68, 0X6B, 0X81, 0XB2, 0X71, 0X64, 0XDA, 0X8B, 0XF8, 0XEB, 0X0F, 0X4B, 0X70, 0X56, 0X9D, 0X35, 34 | 0X1E, 0X24, 0X0E, 0X5E, 0X63, 0X58, 0XD1, 0XA2, 0X25, 0X22, 0X7C, 0X3B, 0X01, 0X21, 0X78, 0X87, 35 | 0XD4, 0X00, 0X46, 0X57, 0X9F, 0XD3, 0X27, 0X52, 0X4C, 0X36, 0X02, 0XE7, 0XA0, 0XC4, 0XC8, 0X9E, 36 | 0XEA, 0XBF, 0X8A, 0XD2, 0X40, 0XC7, 0X38, 0XB5, 0XA3, 0XF7, 0XF2, 0XCE, 0XF9, 0X61, 0X15, 0XA1, 37 | 0XE0, 0XAE, 0X5D, 0XA4, 0X9B, 0X34, 0X1A, 0X55, 0XAD, 0X93, 0X32, 0X30, 0XF5, 0X8C, 0XB1, 0XE3, 38 | 0X1D, 0XF6, 0XE2, 0X2E, 0X82, 0X66, 0XCA, 0X60, 0XC0, 0X29, 0X23, 0XAB, 0X0D, 0X53, 0X4E, 0X6F, 39 | 0XD5, 0XDB, 0X37, 0X45, 0XDE, 0XFD, 0X8E, 0X2F, 0X03, 0XFF, 0X6A, 0X72, 0X6D, 0X6C, 0X5B, 0X51, 40 | 0X8D, 0X1B, 0XAF, 0X92, 0XBB, 0XDD, 0XBC, 0X7F, 0X11, 0XD9, 0X5C, 0X41, 0X1F, 0X10, 0X5A, 0XD8, 41 | 0X0A, 0XC1, 0X31, 0X88, 0XA5, 0XCD, 0X7B, 0XBD, 0X2D, 0X74, 0XD0, 0X12, 0XB8, 0XE5, 0XB4, 0XB0, 42 | 0X89, 0X69, 0X97, 0X4A, 0X0C, 0X96, 0X77, 0X7E, 0X65, 0XB9, 0XF1, 0X09, 0XC5, 0X6E, 0XC6, 0X84, 43 | 0X18, 0XF0, 0X7D, 0XEC, 0X3A, 0XDC, 0X4D, 0X20, 0X79, 0XEE, 0X5F, 0X3E, 0XD7, 0XCB, 0X39, 0X48] 44 | 45 | ''' 46 | 算法模式 47 | ''' 48 | SM4_ECB = 0x01 49 | SM4_CBC = 0x02 50 | 51 | ''' 52 | CBC模式加解密初始向量 53 | ''' 54 | CBC_IV = '00000000000000000000000000000000' 55 | 56 | def _line_conv_L(srcdata): 57 | ''' 58 | 线性变换 L C=L(B)=B^(B<<<2)^(B<<<10)^(B<<<18)^(B<<<24) 59 | B : 一个word 60 | ''' 61 | if common.is_word(srcdata) == False: 62 | raise Exception('源数据不在word定义范围[0x00000000 - 0xFFFFFFFF],不能进行变换计算') 63 | 64 | return srcdata ^ common.lrotate(srcdata, 2) ^ common.lrotate(srcdata, 10) ^ common.lrotate(srcdata, 18) ^ common.lrotate(srcdata, 24) 65 | 66 | def _line_conv_LN(srcdata): 67 | ''' 68 | 线性变换 L' C=L'(B)=B^(B<<<13)^(B<<<23) 69 | B : 一个word 70 | ''' 71 | if common.is_word(srcdata) == False: 72 | raise Exception('源数据不在word定义范围[0x00000000 - 0xFFFFFFFF],不能进行变换计算') 73 | 74 | return srcdata ^ common.lrotate(srcdata, 13) ^ common.lrotate(srcdata, 23) 75 | 76 | def _sbox_conv(srcdata): 77 | ''' 78 | S 盒变换,输入'ef',则经 S 盒后的值为表中第 e 行和第 f列的值,Sbox('ef')= '84' 79 | ''' 80 | if common.is_byte(srcdata) == False: 81 | raise Exception('源数据不在byte定义范围[0x00 - 0xFF],不能进行S 盒变换计算') 82 | 83 | return SM4_SBOX[srcdata] 84 | 85 | def _no_line_conv(srcdata): 86 | ''' 87 | 非线性变换 将一个word通过S 盒转换为另外一个word 88 | ''' 89 | if common.is_word(srcdata) == False: 90 | raise Exception('源数据不在word定义范围[0x00000000 - 0xFFFFFFFF],不能进行变换计算') 91 | 92 | four = srcdata & 0x000000FF 93 | three = (srcdata & 0x0000FF00) >> 8 94 | secod = (srcdata & 0x00FF0000) >> 16 95 | first = (srcdata & 0xFF000000) >> 24 96 | 97 | return (SM4_SBOX[first] << 24) | (SM4_SBOX[secod] << 16) | (SM4_SBOX[three] << 8) | (SM4_SBOX[four]) 98 | 99 | def _t_conv(srcdata): 100 | ''' 101 | T 是一个可逆变换,由非线性变换 τ 和线性变换 L 复合而成,即 T(.)=L(τ(.)) 102 | ''' 103 | if common.is_word(srcdata) == False: 104 | raise Exception('源数据不在word定义范围[0x00000000 - 0xFFFFFFFF],不能进行变换计算') 105 | 106 | return _line_conv_L(_no_line_conv(srcdata)) 107 | 108 | def _tn_conv(srcdata): 109 | ''' 110 | TN 是一个可逆变换,由非线性变换 τ 和线性变换 L' 复合而成,即 T(.)=L'(τ(.)) 111 | ''' 112 | if common.is_word(srcdata) == False: 113 | raise Exception('源数据不在word定义范围[0x00000000 - 0xFFFFFFFF],不能进行变换计算') 114 | 115 | return _line_conv_LN(_no_line_conv(srcdata)) 116 | 117 | def _generate_ext_keys(initkey): 118 | ''' 119 | 通过密钥扩展算法生成加密算法的轮密钥 120 | ''' 121 | if len(initkey) % 2 != 0: 122 | raise Exception('加密密钥长度[%s]错误' % len(initkey)) 123 | if common.IsHexCharacter(initkey) == False: 124 | raise Exception('加密密钥含有非法字符(非16进制字符)') 125 | MK = (initkey[:8], initkey[8:16], initkey[16:24], initkey[24:]) 126 | K = [] 127 | for i in xrange(0, len(MK)): 128 | K.append(common.Xor(int(MK[i], 16), SM4_FK[i])) 129 | 130 | for i in xrange(0, 32): 131 | xorrsp = common.Xor(common.Xor(common.Xor(K[i + 1], K[i + 2]), K[i + 3]), SM4_CK[i]) 132 | K.append(common.Xor(K[i], _tn_conv(xorrsp))) 133 | 134 | return K[4:] 135 | 136 | class SM4(object): 137 | ''' 138 | 国家密码对称算法类 139 | 该算法的分组长度为 128 比特,密钥长度为 128 比特。加密算法与密钥扩展算法都采用 32 轮非线性迭代结构。 140 | 解密算法与加密算法的结构相同,只是轮密钥的使用顺序相反,解密轮密钥是加密轮密钥的逆序。 141 | ''' 142 | 143 | def __init__(self, key='00000000000000000000000000000000'): 144 | ''' 145 | key : 用来加密数据的密钥,长度为128bits hexstring 146 | ''' 147 | self.key = key 148 | self.fk = SM4_FK 149 | self.ck = SM4_CK 150 | self.sbox = SM4_SBOX 151 | self.extkeys = _generate_ext_keys(key) 152 | 153 | def __str__(self): 154 | return 'sm4 object, key : %s' % self.key 155 | 156 | def _sm4_encrypt_128bits(self, message): 157 | ''' 158 | 单组128bits加密 159 | ''' 160 | if len(message) != 32: 161 | raise Exception('原始分组数据长度错误,单个分组长度为128bits') 162 | if common.IsHexCharacter(message) == False: 163 | raise Exception('原始数据包含非法字符(非16进制字符)') 164 | 165 | X = [int(message[:8], 16), int(message[8:16], 16), int(message[16:24], 16), int(message[24:], 16)] 166 | for i in xrange(0, 32): 167 | xorrsp = common.Xor(common.Xor(common.Xor(X[i + 1], X[i + 2]), X[i + 3]), self.extkeys[i]) 168 | X.append(common.Xor(X[i], _t_conv(xorrsp))) 169 | return '%08X%08X%08X%08X' % (X[35], X[34], X[33], X[32]) 170 | 171 | def _sm4_decrypt_128bits(self, message): 172 | ''' 173 | 单组128bits解密 174 | ''' 175 | if len(message) != 32: 176 | raise Exception('原始分组数据长度错误,单个分组长度为128bits') 177 | if common.IsHexCharacter(message) == False: 178 | raise Exception('原始数据包含非法字符(非16进制字符)') 179 | 180 | X = [int(message[:8], 16), int(message[8:16], 16), int(message[16:24], 16), int(message[24:], 16)] 181 | for i in xrange(0, 32): 182 | xorrsp = common.Xor(common.Xor(common.Xor(X[i + 1], X[i + 2]), X[i + 3]), self.extkeys[31 - i]) 183 | X.append(common.Xor(X[i], _t_conv(xorrsp))) 184 | return '%08X%08X%08X%08X' % (X[35], X[34], X[33], X[32]) 185 | 186 | def sm4_encrypt(self, message, enc_mode): 187 | ''' 188 | message 待加密数据 189 | enc_mode 加密模式 ECB/CBC 190 | ''' 191 | 192 | if len(message) % 32 != 0: 193 | raise Exception('待加密数据长度[%s]错误,需要为32的整倍数(含填充数据)' % len(message)) 194 | 195 | if common.IsHexCharacter(message) == False: 196 | raise Exception('待加密数据含有非法字符(非16进制字符)') 197 | 198 | C = '' 199 | if enc_mode == SM4_ECB: 200 | position = 0 201 | while True: 202 | ''' 203 | 循环加密所有分组 204 | ''' 205 | group = message[position:position + 32] 206 | C += self._sm4_encrypt_128bits(group) 207 | position += 32 208 | if len(message) == position: 209 | break 210 | elif enc_mode == SM4_CBC: 211 | position = 0 212 | iv = CBC_IV 213 | while True: 214 | ''' 215 | 循环加密所有分组 216 | ''' 217 | group = message[position:position + 32] 218 | xorrsp = common.Xor(int(iv,16), int(group, 16)) 219 | iv = self._sm4_encrypt_128bits('%032X' % xorrsp) 220 | C += iv 221 | position += 32 222 | if len(message) == position: 223 | break 224 | else: 225 | pass 226 | return C 227 | 228 | def sm4_decrypt(self, message, dec_mode): 229 | ''' 230 | message 待解密密文数据 231 | dec_mode 解密模式 ECB/CBC 232 | ''' 233 | if len(message) % 32 != 0: 234 | raise Exception('待解密数据长度[%s]错误,需要为32的整倍数' % len(message)) 235 | 236 | if common.IsHexCharacter(message) == False: 237 | raise Exception('待解密数据含有非法字符(非16进制字符)') 238 | 239 | M = '' 240 | if dec_mode == SM4_ECB: 241 | position = 0 242 | while True: 243 | ''' 244 | 循环解密所有分组 245 | ''' 246 | group = message[position:position + 32] 247 | M += self._sm4_decrypt_128bits(group) 248 | position += 32 249 | if len(message) == position: 250 | break 251 | elif dec_mode == SM4_CBC: 252 | position = 0 253 | iv = CBC_IV 254 | while True: 255 | ''' 256 | 循环解密所有分组 257 | ''' 258 | group = message[position:position + 32] 259 | decrsp = self._sm4_decrypt_128bits(group) 260 | M += '%032X' % common.Xor(int(iv,16), int(decrsp, 16)) 261 | position += 32 262 | iv = group 263 | if len(message) == position: 264 | break 265 | else: 266 | pass 267 | return M 268 | 269 | #----------------------------------------------------------------------------------------------------- 270 | if __name__ == '__main__': 271 | from common import * 272 | 273 | ''' 274 | print _sbox_conv(0x01) 275 | print _no_line_conv(0xe1e10101) 276 | 277 | i = 0 278 | for num in _generate_ext_keys('0123456789abcdeffedcba9876543210'): 279 | print 'rk[%02d] = [%08X]' % (i, num) 280 | i += 1 281 | ''' 282 | ''' 283 | print _message_padding('0123456789abcdeffedcba987654', SM4_PAD_PBOC) 284 | print _message_padding('0123456789abcdeffedcba9876543210', SM4_PAD_PBOC) 285 | print _message_padding('0123456789abcdeffedcba98765432103210', SM4_PAD_PBOC) 286 | print _message_padding('0123456789abcdeffedcba987654', SM4_PAD_UNION) 287 | print _message_padding('0123456789abcdeffedcba9876543210', SM4_PAD_UNION) 288 | print _message_padding('0123456789abcdeffedcba98765432103210', SM4_PAD_UNION) 289 | ''' 290 | print 'ECB : ' 291 | sm4 = SM4(key='0123456789abcdeffedcba9876543210') 292 | message = '0123456789abcdeffedcba9876543210' 293 | print '待加密数据: ', message 294 | print '密钥: ', sm4.__str__() 295 | C = sm4.sm4_encrypt(message_padding(message, SM4_PAD_PBOC), SM4_ECB) 296 | print '密文: ', C 297 | M = sm4.sm4_decrypt(C, SM4_ECB) 298 | print '明文: ', M 299 | print '-'*120 300 | print 'ECB : ' 301 | message = u'qqwq' 302 | extmessage = reduce(lambda x, y: x + '%02X' % y, map(ord, list(message)), '') 303 | print 'message: ', message 304 | print 'extmessage: ', extmessage 305 | print '待加密数据: ', extmessage 306 | print '密钥: ', sm4.__str__() 307 | C = sm4.sm4_encrypt(message_padding(extmessage, SM4_PAD_PBOC), SM4_ECB) 308 | print '密文: ', C 309 | M = sm4.sm4_decrypt(C, SM4_ECB) 310 | print '明文: ', M 311 | print '-'*120 312 | print 'CBC : ' 313 | message = '0123456789abcdeffedcba9876543210' 314 | print '待加密数据: ', message 315 | print '密钥: ', sm4.__str__() 316 | C = sm4.sm4_encrypt(message_padding(message, SM4_PAD_PBOC), SM4_CBC) 317 | print '密文: ', C 318 | M = sm4.sm4_decrypt(C, SM4_CBC) 319 | print '明文: ', M 320 | print '-'*120 -------------------------------------------------------------------------------- /sm/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixiangzhike/AlgorithmSM/5b4a9e1977446ef4fb093739c968183e1c48581c/sm/__init__.py -------------------------------------------------------------------------------- /sm/common.py: -------------------------------------------------------------------------------- 1 | # -*-coding:utf-8-*- 2 | ''' 3 | Created on 2016-4-6 4 | 5 | @author: 014731 6 | ''' 7 | 8 | ''' 9 | 填充规则 10 | ''' 11 | SM4_PAD_PBOC = 0x04 12 | PAD_PBOC = '80000000000000000000000000000000' 13 | 14 | SM4_PAD_UNION = 0x08 15 | PAD_UNION = '00000000000000000000000000000000' 16 | 17 | try: 18 | integer_types = (int, long) 19 | except NameError: 20 | integer_types = (int,) 21 | 22 | def is_integer(obj): 23 | return isinstance(obj, integer_types) 24 | 25 | def is_byte(int_num): 26 | ''' 27 | 定义8位为一个byte 28 | byte 范围为 0x00 - 0xFF 29 | ''' 30 | if is_integer(int_num) == False: 31 | return False 32 | if int_num < 0x00 or int_num > 0xFF: 33 | return False 34 | return True 35 | 36 | def is_word(int_num): 37 | ''' 38 | 定义32位为一个word 39 | 即一个字的大小范围为 0x00000000 - 0xFFFFFFFF 40 | ''' 41 | if is_integer(int_num) == False: 42 | return False 43 | if int_num < 0x00000000 or int_num > 0xFFFFFFFF: 44 | return False 45 | return True 46 | 47 | def IsHexCharacter(hexstring): 48 | ''' 49 | 判断字符串中字符是否都是16进制字符 0-9 a-f A-F 50 | ''' 51 | base = [str(x) for x in range(0,10)] + [chr(y) for y in range(ord('A'), ord('A') + 6)] 52 | for character in hexstring: 53 | if character.upper() not in base: 54 | return False 55 | return True 56 | 57 | def lrotate(src, bits): 58 | ''' 59 | 循环左移计算 60 | ''' 61 | if is_integer(src) == False: 62 | raise Exception('源数据不是整数类型,不能进行移位操作') 63 | 64 | return ((src << bits) | (src >> abs(32 - bits))) & 0xFFFFFFFF 65 | 66 | def Xor(data1, data2): 67 | ''' 68 | 异或运算 69 | ''' 70 | if is_integer(data1) == False or is_integer(data2) == False: 71 | raise Exception('源数据不是整数类型,不能进行异或运算') 72 | return data1 ^ data2 73 | 74 | def message_padding(message, rule = 4): 75 | if len(message) % 2 != 0: 76 | raise Exception('待加密数据长度不正确,必须为2的整倍数') 77 | padmsg = '' 78 | if rule == SM4_PAD_PBOC: 79 | ''' 80 | PBOC规范要求填充80 81 | ''' 82 | if len(message) % 32 == 0: 83 | padmsg = message + PAD_PBOC 84 | else: 85 | padmsg = message + PAD_PBOC[0:(len(message) / 32 + 1) * 32 - len(message)] 86 | elif rule == SM4_PAD_UNION: 87 | ''' 88 | UNION规范要求填充00 89 | ''' 90 | if len(message) % 32 == 0: 91 | padmsg = message 92 | else: 93 | padmsg = message + PAD_UNION[0:(len(message) / 32 + 1) * 32 - len(message)] 94 | else: 95 | raise Exception('未知填充规则') 96 | 97 | return padmsg 98 | 99 | def gcd(a, b): 100 | ''' 101 | 求a,b最大公约数 102 | ''' 103 | while b != 0: 104 | c = a%b 105 | a = b 106 | b = c 107 | return a 108 | #------------------------------------------------------------- 109 | if __name__ == '__main__': 110 | print lrotate(0x00000001, 2) 111 | print Xor(0xF0, 0x0F) 112 | print gcd(0xFF00AB,0xAABB00) -------------------------------------------------------------------------------- /sm/common.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixiangzhike/AlgorithmSM/5b4a9e1977446ef4fb093739c968183e1c48581c/sm/common.pyc --------------------------------------------------------------------------------