基于python的DES数据加密算法

使用python实现DES的加解密操作

输入:16位的16进制数
输出:
在这里插入图片描述

import random
import numpy as np


def base_key_product(): # 密钥随机生成
    base_key = []
    for i in range(64):
        base_key.append(random.choice([0, 1]))
    return base_key


def round_key_product(base_key): #生成轮密钥
    pc_1 = [57, 49, 41, 33, 25, 17, 9,
            1, 58, 50, 42, 34, 26, 18,
            10, 2, 59, 51, 43, 35, 27,
            19, 11, 3, 60, 52, 44, 36,
            63, 55, 47, 39, 31, 23, 15,
            7, 62, 54, 46, 38, 30, 22,
            14, 6, 61, 53, 45, 37, 29,
            21, 13, 5, 28, 20, 12, 4]
    pc_2 = [14, 17, 11, 24, 1, 5,
            3, 28, 15, 6, 21, 10,
            23, 19, 12, 4, 26, 8,
            16, 7, 27, 20, 13, 2,
            41, 52, 31, 37, 47, 55,
            30, 40, 51, 45, 33, 48,
            44, 49, 39, 56, 34, 53,
            46, 42, 50, 36, 29, 32]
    left_turn = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]
    PC1_key = []
    C_key = []
    D_key = []
    round_key = []
    # PC-1置换
    for i in range(len(pc_1)):
        PC1_key.append(base_key[pc_1[i] - 1])
    # 置换完成,下面进行划分 C0,D0
    C_key.append(PC1_key[0:28])
    D_key.append(PC1_key[28:56])
    # 进行16轮的循环左移
    for i in range(16):
        C_key.append(left_turn_f(C_key[i], left_turn[i]))
        D_key.append(left_turn_f(D_key[i], left_turn[i]))
    # PC-2置换
    for i in range(16):
        tmp = []
        for j in range(len(pc_2)):
            tmp.append((C_key[i + 1] + D_key[i + 1])[pc_2[j] - 1])
        round_key.append(tmp)
    # over
    return round_key


def left_turn_f(lst, k):  # 左移k个
    return lst[k:] + lst[:k]


def IP(plaintxt):  # 初始置换IP
    ip_list = [58, 50, 42, 34, 26, 18, 10, 2,
               60, 52, 44, 36, 28, 20, 12, 4,
               62, 54, 46, 38, 30, 22, 14, 6,
               64, 56, 48, 40, 32, 24, 16, 8,
               57, 49, 41, 33, 25, 17, 9, 1,
               59, 51, 43, 35, 27, 19, 11, 3,
               61, 53, 45, 37, 29, 21, 13, 5,
               63, 55, 47, 39, 31, 23, 15, 7]
    if (len(plaintxt) != 64):
        print("length of txt is error")
        return
    ip_txt = []
    for i in range(64):
        ip_txt.append(plaintxt[ip_list[i] - 1])
    return ip_txt


def IP_1(txt):
    ip_1_list = [40, 8, 48, 16, 56, 24, 64, 32,
                 39, 7, 47, 15, 55, 23, 63, 31,
                 38, 6, 46, 14, 54, 22, 62, 30,
                 37, 5, 45, 13, 53, 21, 61, 29,
                 36, 4, 44, 12, 52, 20, 60, 28,
                 35, 3, 43, 11, 51, 19, 59, 27,
                 34, 2, 42, 10, 50, 18, 58, 26,
                 33, 1, 41, 9, 49, 17, 57, 25]
    secret = []
    for i in range(64):
        secret.append(txt[ip_1_list[i] - 1])
    return secret


def change_16(plaint_ip_list, key):
    # 这里进行16轮迭代
    L_txt = []
    R_txt = []
    # L0 R0
    L_txt.append(plaint_ip_list[0:32])
    R_txt.append(plaint_ip_list[32:64])
    # 迭代
    for i in range(16):
        # Li <-- Ri-1
        L_txt.append(R_txt[i])

        # Ri <--Li-1 ^ f()
        L = np.array(L_txt[i])
        f_result = np.array(f(key[i], R_txt[i]))

        R_txt.append((L ^ f_result).tolist())

    return R_txt[16] + L_txt[16]  # 最后一轮中不用交换左右分组,故而再次调换恢复原状


def f(K, R):
    # 扩展
    E_48 = np.array(E_box(R))
    # print('E-box')
    # print(E_48)
    key = np.array(K)
    # 异或, S-box
    # np.bitwise_xor(R_48,key)
    result = (E_48 ^ key).tolist()
    # print('xor:')
    # print(result)
    S_32 = S_box(result)
    # print('S-32:')
    # print(S_32)
    # P-box
    P_32 = P_box(S_32)
    # print('P-box:')
    # print(P_32)
    return P_32  # return list


def E_box(R):  # list32
    # E_Box函数完成扩展 32bits-->48bits
    e_box_list = [32, 1, 2, 3, 4, 5,
                  4, 5, 6, 7, 8, 9,
                  8, 9, 10, 11, 12, 13,
                  12, 13, 14, 15, 16, 17,
                  16, 17, 18, 19, 20, 21,
                  20, 21, 22, 23, 24, 25,
                  24, 25, 26, 27, 28, 29,
                  28, 29, 30, 31, 32, 1]
    e_rusult = []
    for i in range(48):
        e_rusult.append(R[e_box_list[i] - 1])

    return e_rusult  # list48


def S_box(txt):  # txt是一串48bit长的列表
    s = []
    s_result = []
    s_box_table = [
        [14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
         0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
         4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
         15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
         ],
        [15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
         3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
         0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
         13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
         ],
        [10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
         13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
         13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
         1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
         ],
        [7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
         13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
         10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
         3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
         ],
        [2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
         14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
         4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
         11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
         ],
        [12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
         10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
         9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
         4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
         ],
        [4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
         13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
         1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
         6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
         ],
        [13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
         1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
         7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
         2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
         ]]
    # 划分s盒子
    for i in range(8):
        s.append(txt[6 * i:6 * i + 6])
        # print(s[i])
    # s盒
    for i in range(8):
        # 提取首尾作为y值,剩下的作为x值,并转化为10进制
        y = int(str(s[i][0]) + str(s[i][5]), 2)
        x = int(''.join(list(map(str, s[i][1:5]))), 2)
        # i 代表第i+1个盒子
        # number 代表盒子中的第几个数
        number = 16 * y + x
        # z 代表对应的10进制数
        z = s_box_table[i][number]
        # 转换为2进制,保持4位数,并转化为列表,元素为字符
        tmp = list(bin(z)[2:].zfill(4))
        # 将列表元素转化为数字
        tmp = list(map(eval, tmp))
        s_result.append(tmp)
    return s_result[0] + s_result[1] + s_result[2] + s_result[3] + s_result[4] + s_result[5] + s_result[6] + s_result[7]


def P_box(S_32):
    p_box_list = [16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30,
                  6, 22, 11, 4, 25]
    p_result = []
    for i in range(32):
        p_result.append(S_32[p_box_list[i] - 1])
    return p_result


def DES(base_key, txt):
    round_key = round_key_product((base_key))
    return IP_1(change_16(IP(txt), round_key))


def DES_Decrypt(str_secret, str_key):  # str str
    # str to list
    secret = list(map(eval, str_secret))
    base_key = list(map(eval, str_key))
    round_key = round_key_product((base_key))

    return IP_1(change_16_decrypt(IP(secret), round_key))


def change_16_decrypt(plaint_ip_list, key):
    # 这里进行16轮迭代
    L_txt = []
    R_txt = []
    # R16L16
    R_txt.append(plaint_ip_list[0:32])
    L_txt.append(plaint_ip_list[32:64])
    # 迭代
    for i in range(16):
        R_txt.append(L_txt[i])

        R = np.array(R_txt[i])
        f_result = np.array(f(key[15 - i], L_txt[i]))
        L_txt.append((R ^ f_result).tolist())

    return L_txt[16] + R_txt[16]


if __name__ == "__main__":
    txt = input("Input the plaint txt\n")  # 16进制
    # txt='0123456789ABCDEF'
    txt = bin(int(txt, 16))[2:]  # 2进制
    if len(txt) < 64:
        txt = txt.zfill(64)  # 小于64bit自动补全
    elif len(txt) > 64:
        print("请先分组,确保小于等于64bit\n")
        exit(0)
    print('明文的二进制表示')
    print(''.join(txt))
    txt = list(map(eval, txt))
    # txt = [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0,
    #       1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1]

    base_key = base_key_product()
    # base_key = [0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0,
    #            1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1]
    # base_key = input("Input the key\n")  # 16进制
    # base_key = (bin(int(base_key, 16))[2:]).zfill(64)  # 2进制
    # base_key=list(map(eval,base_key))
    print('初始密钥:')
    #print(base_key)
    out_base_key = ''.join(str(i) for i in base_key)
    print(out_base_key)
    print('DES加密结果:')
    out_DES_result = ''.join(str(i) for i in DES(base_key, txt))
    print(out_DES_result)
    # 下面开始解密
    print('解密结果:')
    decrypt_result = DES_Decrypt(out_DES_result, out_base_key)
    decrypt_result = ''.join(list(map(str, decrypt_result)))
    print(decrypt_result)
    # a=hex(int(, 2))
    print(hex(int(decrypt_result, 2))[2:])

  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值