python实现DES算法加解密

# 从文件中读取明文
# 对明文进行字符转换成比特流 每64位分一组 最后不足的用0补足
# 对每组的64位比特进行IP置换 分 L,R俩组
# 对L,R进行16轮的Feistel变换
# 使用IP-1(IP逆置换)函数将L,R合并为密文比特流
# 最后将密文比特流转换成密文字符保存
import re
import libnum
import os

IP_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]


IP_re_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]


E  = [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]



P = [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]


S =  [
    [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],
]

#子秘钥生成 置换选择PC_1盒和PC_2盒

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]


#秘钥左移的位数
SHIFT = [1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1]


def read_file():
    try:
        f = open(r"des.txt",'r',encoding = 'utf-8')
        mess = f.read()
        f.close()
        print("文件读取成功")
        return mess
    except IOError:
        print("文件读取失败")

def write_file(message):
    try:
        os.remove(r"des.txt")
        f = open(r"des.txt",'w',encoding = 'utf-8')
        f.write(message)
        f.close()
        print("文件写入成功")
    except IOError:
        print("文件写入失败")

#在分组加解密的时候 我们再bit级上进行操作 ,这里将字符ascii转bit流
def str2bin(message):
    # 字符串转2进制(bit流) 每个字符8个bit 不够补0
    res = ""
    for i in message:
        tmp = bin(ord(i))[2:]
        for j in range(0,8-len(tmp)):
            tmp = '0' + tmp
        res += tmp
    return res


#初始置换IP 
def ip_change(bin_str):
    #输入为64位明文消息 输出为经过初始置换IP的64位消息
    res = ""
    for i in IP_table:
        res += bin_str[i-1]
    return res

#逆初始置换Ip
def ip_re_change(bin_str):
    #输入为经过合并的64位分组消息,输出为64位密文
    res = ""
    for i in IP_re_table:
        res += bin_str[i-1]
    return res

#循环左移操作
def left_turn(my_str,num):
    # 左移 列表拼接
    left_res = my_str[num:len(my_str)]
    left_res = left_res + my_str[0:num]
    return left_res


#密钥的PC-1置换
def change_key1(my_key):
    res = ""
    for i in PC_1:
        res += my_key[i-1]
    return res

#密钥的PC-2置换
def change_key2(my_key):
    res = ""
    for i in PC_2:
        res += my_key[i-1]
    return res

#E盒扩展置换 明文拓展
def e_str(bin_str):
    #输入为32位的右分组消息,输出为48位的经过扩展置换的消息
    res = ""
    for i in E:
        res += bin_str[i-1]
    return res

#异或
def str_xor(str1,str2):
    res = ""
    for i in range(0,len(str1)):
        xor_res = int(str1[i]) ^ int(str2[i]) #转int类型再异或
        if xor_res == 1:
            res += '1'
        if xor_res == 0:
            res += '0'
    return res

#S盒非线性代换
def s_box(my_str):
    # 异或运算结束后,我们需要将48bit缩减位32bit,分组使用S盒置换
    res = ""
    c = 0   # 第几个S盒 (S0-S7)
    for i in range(0,len(my_str),6):   # 6 * 8 6位一组,循环8次
        now_str = my_str[i:i+6]        # 第i个分组,切片
        row = int(now_str[0]+now_str[5],2) #第一位和第六位行号
        col = int(now_str[1:5],2)          #第二为到第五位列号
        num = bin(S[c][row * 16 + col])[2:] #一行16个元素 第 row * 16 +col个元素
        for i in range(0,4-len(num)):      #补全4位输出
            num = '0' + num
        res += num
        c += 1
    return res

# P盒线性置换
# P盒将32位输入经过P盒置换后再与最初的L分组进行异或,然后左右换位进行下一轮f
def p_box(bin_str):
    res = ""
    for i in P:
        res += bin_str[i-1]
    return res

#16轮变换后,最后一轮不交换左右分组,直接合并比特流,得到加密后的56位比特

#将密文bit流转为密文字符
def bin2str(message):
    res = ""
    tmp = re.findall(r'.{8}',message) #八位一字符
    for i in tmp:
        res += chr(int(i,2))   #二进制字符串转十进制ascii 再转字符
    return res

#F轮函数实现 16轮 先将明文32bit拓展为48bit,然后与子密钥Ki进行按位模加运算(即异或),得到的结果按每组6位分为8组,再经过S盒,从每6位中选择出4位,得到32比特,经过P盒置换后,得到最终的32位结果
'''
1、扩展置换
2、与轮密钥按位异或
2、经过S盒将每组从48bit缩短到32bit
3、经过P盒置换得到32bit
'''
def fun_f(bin_str,key):   #32位R分组 和 轮密钥
    first_output = e_str(bin_str)    #扩展置换
    second_output = str_xor(first_output,key) #和轮密钥按位异或
    third_output = s_box(second_output)       #经过S盒 每组6位缩减到4位(48bit缩减位32bit)
    last_output = p_box(third_output)         #经过p盒线性置换(换位)
    return last_output

# 轮密钥生成 16轮
'''
1、初始置换选择PC-1
2、循环移位(左移)运算  移位次序表中第LS1,LS2,LS9,LS16次是循环左移1位变换,其他为循环左移2为变换
3、置换选择PC-2 最终选择出48bit子密钥
'''
def gen_key(key):
    key_list = []
    divide_output = change_key1(key)
    key_C0 = divide_output[0:28]     # 分为左右俩部分 每部分占28bit
    key_D0 = divide_output[28:]
    # 经过循环左移   i是左移位数
    for i in SHIFT:
        key_C = left_turn(key_C0,i)     # 左半部分循环左移
        key_D = left_turn(key_D0,i)     # 右半部分左移
        key_output = change_key2(key_C + key_D) # 经过PC-2盒置换选择出48位子秘钥
        key_list.append(key_output)
    return key_list

# des加密
'''
1、初始置换
2、明文分L、R
3、轮函数加密 16轮  注意最后一次不用换位
4、左右部分合并
5、逆初始置换
6、返回并将密文写入文件
'''
def des_encrypto(bin_message,bin_key):
    mes_ip_bin = ip_change(bin_message) # ip置换
    key_lst = gen_key(bin_key)          # 子秘钥生成
    mes_left = mes_ip_bin[0:32]         # 明文分组 L、R
    mes_right = mes_ip_bin[32:]
    for i in range(0,15):              # 注意!!! 第16次不用换位
        mes_tmp = mes_right
        f_result = fun_f(mes_tmp,key_lst[i])   # R组32位与子密钥经过F函数后
        mes_right = str_xor(f_result,mes_left) # F函数后的结果与L组 进行异或 结果赋予R组
        mes_left = mes_tmp                     # 原R组直接赋值给L组
    f_result = fun_f(mes_right,key_lst[15])     # 最后一次不用换位
    mes_fin_left = str_xor(mes_left,f_result)
    mes_fin_right = mes_right
    fin_message = ip_re_change(mes_fin_left + mes_fin_right)  # 合并后 进行逆IP置换
    return fin_message

# 64位二进制解密的测试,注意秘钥反过来了,不要写错了
def des_decrypto(bin_mess,bin_key):
    mes_ip_bin = ip_change(bin_mess)
    #bin_key = input_key_judge(str2bin(key))
    key_lst = gen_key(bin_key)
    cipher_left = mes_ip_bin[0:32]
    cipher_right = mes_ip_bin[32:]
    for i in list(range(1,16))[::-1]:   #表示逆转列表调用
        mes_tmp = cipher_right
        cipher_right = str_xor(cipher_left,fun_f(cipher_right,key_lst[i]))
        cipher_left = mes_tmp
    fin_left = str_xor(cipher_left,fun_f(cipher_right,key_lst[0]))
    fin_right = cipher_right
    fin_output  = fin_left + fin_right
    res = ip_re_change(fin_output) 
    return res

def deal_mess(bin_mess):
    # 判断并补全64位bit流
    ans = len(bin_mess)
    if ans % 64 != 0:
        for i in range(64 - (ans % 64)):
            bin_mess += "0"
    return bin_mess

def check_key(bin_key):
    # 密钥不够64位补0
    ans = len(bin_key)
    if len(bin_key) < 64:
        if ans % 64 != 0:
            for i in range(64 - (ans % 64)):
                bin_key += '0'
    return bin_key

# 规范明文和密钥后完整DES加密
def encrypto(message,key):
    bin_mess = deal_mess(str2bin(message)) # 明文的二进制bit流 判断是64的倍数 不够补全
    res = ""
    bin_key = check_key(str2bin(key))      # 得到密钥的二进制流 也是64的倍数
    tmp = re.findall(r'.{64}',bin_mess)    # 字符加密 只能64bit一组
    for i in tmp:
        res += des_encrypto(i,bin_key)     # 分组加密后的字符连接
    return res

def decrypto(message,key):
    bin_mess = deal_mess(str2bin(message))
    res = ""
    bin_key = check_key(str2bin(key))
    tmp = re.findall(r'.{64}',bin_mess)
    for i in tmp:
        res += des_decrypto(i,bin_key)
    res = bin2str(res)
    return res

def main():
    print("请输入序号,选择对应的功能:")
    print("--# 1.使用DES加密")
    print("--# 2.使用DES解密")
    mode = input()
    if mode == '1':
        print("--# 请输入信息输入字符串不能为空:")
        message = input().replace(' ','')
        print("--# 请输入你的秘钥:")
        key = input().replace(' ','')
        s = encrypto(message,key)
        out_mess = bin2str(s)
        print("--# 加密过后的内容:"+ out_mess)
        write_file(out_mess)
        
    elif mode == '2':
        # print("--# 请输入信息输入字符串不能为空:")
        # message = input().replace(' ', '')
        print("--# 请输入你的秘钥:")
        key = input().replace(' ', '')
        message = read_file()
        s = decrypto(message, key)
        #out_mess = bin2str(s)
        print("--# 解密后的信息:"+ s)
    else:
        print("--# 请重新输入!")


if __name__ == '__main__':
    while True:
        main()

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值