DES加解密实验 python实现 详细注释

为了便于理解,每一步都添加了详细的注释。

主算法
if __name__ == '__main__':
    Path1 = input('输入 要分析的文件 的完整路径:')
    Path2 = input('输入 导出文件 的完整路径:')
    key = input('输入密钥key:')
    while len(list(bytes(key, encoding="utf-8"))) > 8:
        print("密钥长度应该小于8字节!")
        key = input("请输入密钥key:")
    choose = input('1文件加密 2文件解密  : ')

    key = list(bytes(key, encoding="utf-8"))
    with open(Path1, 'rb') as fp:
        text = list(fp.read())

    # 不满64位【8字节】的倍数补0
    for i in range((8 - len(text) % 8)if (len(text) % 8!=0) else 0):
        text.append(0)  # 内容转换为2进制数据,64位的倍数
    if len(key)==0:key.append(0)
    for i in range((8 - len(key) % 8)if (len(key) % 8!=0) else 0):
        key.append(0)

    key_bin = bin_byte(key)  # 密钥转换为2进制数据,64位
    K = create_key(key_bin,choose)  # 生成16组子密钥,48位

    thetext = ''
    for i in range(len(text) // 8):  # 所有的字节序列每64位【8字节】加密
        text_bin = bin_byte(text[i * 8:(i + 1) * 8])  # 转换为二进制数据,64位
        init_data = RE(text_bin, init_table)  # 初始置换后的二进制数据,64位
        L, R = init_data[:32], init_data[32:]  # 初始置换的数据切片为左右两半部分,各32位
        for li in range(16):  # 16次迭代
            N = f(R, K[li])  # f的输出是32位
            L, R = R, "".join([str(int(L[i]) ^ int(N[i])) for i in range(32)])  # 与左半部分异或形成新的右半部分, 32位
        L,R=R,L             # 最后一轮不做交换
        thetext += RE(L + R, final_table)  # 终止置换后的2进制数据,64位
    sequence = byte_bin(thetext)           # 将所有的 2进制数据 转换为字节序列
    with open(Path2,"wb")as fp:
        fp.write(bytes(sequence))
核心F函数,迭代使用
def f(text,key):
    text=RE(text, expand_table)             # 对数据扩展置换,48位
    input = "".join([str(int(text[i]) ^ int(key[i])) for i in range(48)])  # 异或运算的结果作为输入块,48位
    output=""
    for i in range(8):                      # 等分8块,6位
        data=input[i * 6:(i + 1) * 6]
        row=int(data[0]+data[-1],2)         # 第一位和最后一位变成行数
        col=int(data[1:-1],2)               # 中间四位变成列数
        output+="{:04b}".format(sbox_table[i][row][col])      # 盒子中取出数变为2进制,4位
    return RE(output,pbox_table)            # 32位放到P盒置换后得到32位
生成16组子密钥
def create_key(key_bin,choose):
    '16 次迭代生成 16组子密钥K'
    key = RE(key_bin,key_table)            # 对key密钥置换,56位
    Lkey,Rkey=key[:28],key[28:]             # 密钥置换的数据切片,各28位
    K=[]
    for index in range(16):
        Lkey=left_move(Lkey, round_table[index])
        Rkey=left_move(Rkey, round_table[index])
        key_bin = Lkey + Rkey  # 循环左移,56位
        K.append(RE(key_bin, compress_table))  # 对密钥压缩置换,48位
    if choose!='1':K.reverse()                  # 解密过程密钥反转
    return K
一句话实现循环左移
def left_move(text,start):
    '循环左移'
    return text[start:]+text[0:start]
置换算法
def RE(text,theTable):
    '置换算法'
    str=""
    for i in theTable:str+=text[i-1]
    return str
二进制字符串转字节序列
def byte_bin(text):
    '二进制字符串转字节序列'
    return [int(text[i * 8:(i + 1) * 8],2) for i in range(len(text) // 8)]
将字节序列转换为64位二进制字符串
def bin_byte(text):
    '将字节序列转换为64位二进制字符串'
    binary=""
    for i in range(len(text)):
        binary+="{:08b}".format(text[i])
    return binary
各种表:
# 初始置换表
init_table=[ 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  ]
# 终止置换表
final_table=[ 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  ]
# 扩展置换表
expand_table=[ 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  ]
# 压缩置换表
compress_table=[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 ]

# 密钥置换表
key_table=[ 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 ]
# P盒置换表
pbox_table=[ 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  ]

# 8个S盒置换表
sbox_table=[
    # S1
     [[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]],
    # S2
     [[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]],
    # S3
     [[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]],
    # S4
     [[ 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]],
    # S5
     [[ 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]],
    # S6
     [[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]],
    # S7
     [[ 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]],
    # S8
     [[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]]
    ]
# 轮转调度表
round_table=[1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]

复制所有的代码,直接运行即可。加密解密的数据会导出到文件里。

存在的问题:
  • 1、密钥应该在输入的时候就是64位,其中8位时奇偶校验码,但那是其他人员的工作了。在我处理的时候,不足64位会补0。运行中是没问图的,但不符实际要求。
  • 2、主代码的16次迭代最后一次是不进行交换的,直接运算完得到数据即可。但我为了代码的美观简洁,会进行17次交换。这使得代码在运行时效率会降低。而使用对称加密算法就是图加密速度快,所以······
  • 3、验收密码学的作业通过啦,C类课还要写这种代码······
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值