(密码学)(crypto)IDEA_Crypto(ECB模式)——python实现

(密码学)(crypto)IDEA_Crypto(ECB模式)——python实现

四月 30, 2020
# -*- coding:utf-8 -*-

def FindMODreverse(a,m):                        # 欧几里得除法求模逆元
    m_tmp = m
    x_1,x_2 = 1,0
    y_1,y_2 = 0,1
    while m != 0:
        q = a//m
        x_2,y_2,m,x_1,y_1,a = (x_1 - q * x_2),(y_1 - q * y_2),a % m,x_2,y_2,m
    while x_1 < 0:
        x_1 += m_tmp
    while x_1 >= m_tmp:
        x_1 -= m_tmp
    return x_1



def ROL(lit,num):                               # 循环左移 num 位
    return lit[num:] + lit[:num]



def idea_xor(x,y):                              # 逐位异或
    tmp = '' ; i = 0
    while True:
        try:
            tmp += str(int(x[i],2)^int(y[i],2))
            i += 1
        except:
            return tmp



def idea_add(x,y):                              # 模65536相加
    x = int(x,2) ; y = int(y,2)
    z = ( x + y ) % 65536
    z = bin(z)[2:]
    tmp = '0'*(16 - len(z)) + z
    return tmp



def idea_mul(x,y):                              # 模65537相乘
    x = int(x,2) ; y = int(y,2)
    if x == 0:
        x = 2^16
    if y == 0:
        y = 2^16
    z = ( ( x * y ) % 65537 ) % 65536
    z = bin(z)[2:]
    tmp = '0'*(16 - len(z)) + z
    return tmp



def idea_encode(m,num,key):                     # 加密过程
    x_array = [m[i*16:i*16+16] for i in range(4)]
    z_array = key[num*6:num*6+6]

    if num < 8:
        out_1 = idea_mul(x_array[0],z_array[0])
        out_2 = idea_add(x_array[1],z_array[1])
        out_3 = idea_add(x_array[2],z_array[2])
        out_4 = idea_mul(x_array[3],z_array[3])
        out_5 = idea_mul(z_array[4],idea_xor(out_1,out_3))
        out_6 = idea_mul(z_array[5],idea_add(idea_xor(out_2,out_4),out_5))
        out_7 = idea_add(out_5,out_6)

        w_1 = idea_xor(out_1,out_6)
        w_2 = idea_xor(out_3,out_6)
        w_3 = idea_xor(out_2,out_7)
        w_4 = idea_xor(out_4,out_7)

        c = w_1 + w_2 + w_3 + w_4

        num += 1
        c = idea_encode(c,num,key)
    else:
        y_1 = idea_mul(x_array[0],z_array[0])
        y_2 = idea_add(x_array[2],z_array[1])
        y_3 = idea_add(x_array[1],z_array[2])
        y_4 = idea_mul(x_array[3],z_array[3])
        c = y_1 + y_2 + y_3 + y_4

    return c



def IDEA_Crypto(cm_str,key,mode):
    if mode == 0:
        if len(cm_str) % 8 != 0:                         # 对明文进行填充
            cm_str += '\x00' * ( 8 - len(cm_str) % 8 )

        m_bin = ''                                       # 将明文转化为二元序列
        for i in cm_str.encode('utf-8'):
            i = bin(i)[2:]
            m_bin += '0'*(8 - len(i)) + i
    else:                                                # 将密文转化为二元序列
        c_bin = bin(int(cm_str,16))[2:]
        if len(c_bin) % 8 != 0:
            c_bin = '0'*(8 - (len(c_bin) % 8)) + c_bin

    key_bin = ''                                         # 将密钥转化为二元序列
    for i in key.encode('utf-8'):
        i = bin(i)[2:]
        key_bin += '0'*(8 - len(i)) + i

    key_encrypt_array = []                                       # 生成加密子密钥
    for i in range(6):
        for j in [key_bin[k*16:k*16+16] for k in range(8)]:
            key_encrypt_array.append(j)
        key_bin = ROL(key_bin,25)
    else:
        key_encrypt_array.extend([key_bin[k*16:k*16+16] for k in range(8)][:4])

    key_decrypt_array = [] ; flag = 0                            # 生成解密子密钥
    key_tmp_array = key_encrypt_array[::-1]
    for i in [key_tmp_array[i*6:i*6+6] for i in range(8)]:
        i[:4] = i[3::-1] ; i[-2:] = i[:-3:-1]

        if flag == 0:                                            # 第一轮和最后一轮的第二三子密钥特殊取值
            Addrev = bin((65536 - int(i[1],2)) % 65536)[2:]
            i[1] = '0'*(16-len(Addrev)) + Addrev
            Addrev = bin((65536 - int(i[2],2)) % 65536)[2:]
            i[2] = '0'*(16-len(Addrev)) + Addrev
            flag += 1
        else:
            Addrev = bin((65536 - int(i[1],2)) % 65536)[2:]
            tmp_1 = '0'*(16-len(Addrev)) + Addrev
            Addrev = bin((65536 - int(i[2],2)) % 65536)[2:]
            tmp_2 = '0'*(16-len(Addrev)) + Addrev
            i[1] = tmp_2
            i[2] = tmp_1

        Modrev = bin(FindMODreverse(int(i[0],2),65537))[2:]
        i[0] = '0'*(16-len(Modrev)) + Modrev
        Modrev = bin(FindMODreverse(int(i[3],2),65537))[2:]
        i[3] = '0'*(16-len(Modrev)) + Modrev

        key_decrypt_array.extend(i)
    else:                                                       # 最后一轮第九轮的解密密钥
        i = key_tmp_array[-4:][::-1]

        Addrev = bin((65536 - int(i[1],2)) % 65536)[2:]
        i[1] = '0'*(16-len(Addrev)) + Addrev
        Addrev = bin((65536 - int(i[2],2)) % 65536)[2:]
        i[2] = '0'*(16-len(Addrev)) + Addrev
        Modrev = bin(FindMODreverse(int(i[0],2),65537))[2:]
        i[0] = '0'*(16-len(Modrev)) + Modrev
        Modrev = bin(FindMODreverse(int(i[3],2),65537))[2:]
        i[3] = '0'*(16-len(Modrev)) + Modrev

        key_decrypt_array.extend(i)

    if mode == 0:                                   # 文本二元序列的分组
        mc_array = [ m_bin[i*64:i*64+64] \
            for i in range(int(len(m_bin) / 64)) ]  
    else:
        mc_array = [ c_bin[i*64:i*64+64] \
            for i in range(int(len(c_bin) / 64)) ]

    cm_array = []                                   # 求结果分组
    if mode == 0:
        for i in mc_array:
            cm_array.append(idea_encode(i,0,key_encrypt_array))
    else:
        for i in mc_array:
            cm_array.append(idea_encode(i,0,key_decrypt_array))

    cm = ''                                      # 将结果分组转换为对应的十六进制内容
    for i in cm_array:
        tmp = hex(int(i,2))[2:]
        if len(tmp) * 4 != len(i):
            tmp = '0'*int(len(i) / 4 - len(tmp)) + tmp
        cm += tmp

    if mode == 0:
        print('密文:' + cm)
    else:
        print('明文(hex):' + cm)

    return cm

if __name__ == "__main__":
    m = '1234567812345678'
    key = '1234567812345678'
    c = IDEA_Crypto(m,key,0)
    m_tmp = IDEA_Crypto(c,key,1)
'''
隐藏