"""
对称加密算法,解密、加密密钥相同,顺序相反;加密密钥:k1,k2,k3,k4 解密密钥:k4,k3,k2,k1
国密算法 SMS4 加密分组长度 128 bit 加密密钥位数与其等同
和 SMS4 文档明文加密结果相同
successfully!!!!!!
"""
SBox=np.array([0xd6,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,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6,
0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8,
0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35,
0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87,
0xd4,0x00,0x46,0x57,0x9f,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])
SBox=SBox.reshape((16,16))
def S(plaintext):
plaintext=bin(plaintext)
s_plaintext=''
plaintext=change_binary(plaintext)
for i in range(4):
bin_8=plaintext[8*i:8*(i+1)]
x=int(bin_8[:4],2)
y=int(bin_8[4:],2)
temp=hex(SBox[x, y])
s_plaintext += fill_up_0_to_16(temp,2,True)
return s_plaintext
def loop_k(s_plaintext,k,L_or_R='L'):
s_plaintext_2=bin(int(s_plaintext, 16))
s_plaintext=change_binary(s_plaintext_2)
if L_or_R=='L':
return s_plaintext[k:]+s_plaintext[:k]
elif L_or_R=='R':
return s_plaintext[-k:]+s_plaintext[:len(s_plaintext)-k]
def L_m(s_plaintext):
s_0=int(s_plaintext,16)
s_2=int(loop_k(s_plaintext,2),2)
s_10=int(loop_k(s_plaintext,10),2)
s_18=int(loop_k(s_plaintext,18),2)
s_24=int(loop_k(s_plaintext,24),2)
return s_0^s_2^s_10^s_18^s_24
''''
密钥扩展算法
'''
FK=np.array([0xa3b1bac6,0x56aa3350,0x677d9197,0xb27022dc])
CK=np.array(['00070e15', '1c232a31', '383f464d', '545b6269', '70777e85', '8c939aa1', 'a8afb6bd', 'c4cbd2d9',
'e0e7eef5', 'fc030a11', '181f262d', '343b4249', '50575e65', '6c737a81', '888f969d', 'a4abb2b9',
'c0c7ced5', 'dce3eaf1', 'f8ff060d', '141b2229', '30373e45', '4c535a61', '686f767d', '848b9299',
'a0a7aeb5', 'bcc3cad1', 'd8dfe6ed', 'f4fb0209', '10171e25', '2c333a41', '484f565d', '646b7279'])
def build_CK():
CK_=['']*32
for i in range(32):
for j in range(4):
strj=hex((4*i+j)*7%256)[2:]
if len(strj)!=2:
strj='0'*(2-len(strj))+strj
CK_[i] +=strj
return CK_
def L_c(s_key):
s_0=int(s_key,16)
s_13=int(loop_k(s_key,13),2)
s_23=int(loop_k(s_key,23),2)
return s_0^s_13^s_23
'''
求轮密钥 rki(i=0,1,2...31)
初始密钥 MK=(MK0,MK1,MK2,MK3)
(K0,K1,K2,K3)=(FK0^MK0,FK1^FK1,FK2^MK2,FK3^MK3)
rk(i)=K(i+4)=K(i)^T'(K(i+1)^K(i+2)^K(i+3)^CK(i))
'''
def key_extend(key_128):
MK=['']*4
for i in range(4):
MK[i]=key_128[2+8*i:2+8*(i+1)]
K=[0]*36
Key=[0]*32
for i in range(4):
mk=int(MK[i],16)
fk=FK[i]
K[i]=mk^fk
for i in range(0,32):
K_tmp=K[i+1]^K[i+2]^K[i+3]^int(CK[i],16)
s_K_tmp=S(K_tmp)
L_s_K_tmp=L_c(s_K_tmp)
K[i+4]=K[i]^L_s_K_tmp
for j in range(4,36):
temp=hex(K[j])
Key[j-4]='0x'+fill_up_0_to_16(temp,8,True)
return Key
"""
加密明文的主加密函数 输入 16进制字符串 明文,例:'0x1f6c3b...' 共128 bit
"""
def SMS4_en_decoding(plaintext,key):
X=[0]*36
for i in range(4):
X[i]=int(plaintext[2+8*i:2+8*(i+1)],16)
for i in range(32):
p_tmp=X[i+1]^X[i+2]^X[i+3]^int(key[i],16)
s_p_tmp=S(p_tmp)
L_s_p_tmp=L_m(s_p_tmp)
X[i+4]=X[i]^L_s_p_tmp
for i in range(36):
temp=hex(X[i])
X[i]='0x'+fill_up_0_to_16(temp,8,True)
return X
def X35_X32(X):
ciphertext=''
for i in range(35,31,-1):
ciphertext+=change_hex(X[i])
return ciphertext
if __name__=="__main__":
plaintext='e'*105
print('明文',plaintext)
key= 'REde4$%^&()><1rd'
if key_to_16(key):
key=key_to_16(key)
else:
print('密钥错误,请重设');exit(10)
team=plaintext_to_team16(plaintext)
ciphertext=''
Key=[]
Key = key_extend(key)
for i in range(len(team)-1):
c = SMS4_en_decoding('0x'+team[i], Key)
ciphertext+=X35_X32(c)
if len(str(team[-1]))!=2:
temp7='0'*(2-len(str(team[-1])))+str(team[-1])
else:
temp7=str(team[-1])
ciphertext+=temp7
print("密文:"+ciphertext)
print(len(ciphertext))
plaintext16=[]
for i in range(len(team)-1):
if cipher16_divide_group(ciphertext[:-2]):
group=cipher16_divide_group(ciphertext[:-2])
else:
print('密文分组出现错误');exit(11)
m = SMS4_en_decoding('0x'+group[i], Key[::-1])
plaintext16.append(X35_X32(m))
plaintext16.append(int(ciphertext[-2:]))
print(plaintext16)
restore=restore_16_to_plaintext(plaintext16)
print("恢复成原明文:",restore)
if plaintext==restore:
print("加解密成功")
else:
print("加解密失败")
PS: 完整代码链接:国密算法SM2和SM4标准加密代码及官方文档 (python 源代码)