文件安全传输python实现(MD5、RSA、DES,不调用现成的密码算法的包)

一、框架

实现文件安全传输的原型如下图所示,消息的哈希值用公钥加密算法和发送方的秘密钥签名后与消息链接,再对链接后的结果用单钥加密算法加密。
在这里插入图片描述
各模块使用的算法:
哈希算法使用MD5。
非对称密码算法使用RSA。
对称加密算法使用DES。
语言:
Python 3.7

二、MD5哈希算法

my_md5.py:

#-*-coding:UTF-8 -*-
from math import floor,sin
from bitarray import bitarray
from enum import Enum
import struct

#初始化MD5缓冲区
class Buffer(Enum):
    A = 0x67452301
    B = 0xEFCDAB89
    C = 0x98BADCFE
    D = 0x10325476

class MyMd5(object):
    buffers = {Buffer.A: None,Buffer.B: None,
               Buffer.C: None,Buffer.D: None,
              }

    @classmethod
    #消息填充
    def message_fill(cls):
        bit = bitarray(endian="big")
        bit.frombytes(cls.string_M.encode("utf-8"))
        bit.append(1)
        
        while bit.length() % 512 != 448: #如果mod512不等于448,填充0
            bit.append(0)
        
        return bitarray(bit, endian="little")#小端

    @classmethod
    #附加消息的长度
    def additional_message_length(cls, message_fill_result):
        length = (len(cls.string_M) * 8) % pow(2, 64)
        
        #将length转成64bit的小端形式
        message_length = bitarray(endian="little")
        message_length.frombytes(struct.pack("<Q", length))
        result = message_fill_result.copy()
        result.extend(message_length)
        
        return result

    @classmethod
    #对MD5缓冲区初始化
    def buffer_initialize(cls):
        for buffer_type in cls.buffers.keys():
            cls.buffers[buffer_type] = buffer_type.value
            
        A = cls.buffers[Buffer.A]
        B = cls.buffers[Buffer.B]
        C = cls.buffers[Buffer.C]
        D = cls.buffers[Buffer.D]

    @classmethod
    #以分组为单位对消息进行处理
    def message_handing(cls, additional_message_length_result):
		#定义循环左移函数
        ROL = lambda x, n: (x << n) | (x >> (32 - n))

        #定义模加函数
        mod_add = lambda a, b: (a + b) % pow(2, 32)
		
        #定义逻辑函数
        F = lambda x, y, z: (x & y) | (~x & z)
        G = lambda x, y, z: (x & z) | (y & ~z)
        H = lambda x, y, z: x ^ y ^ z
        I = lambda x, y, z: y ^ (x | ~z)

        #计算常数表T
        T = [floor(pow(2, 32) * abs(sin(i + 1))) for i in range(64)]

        #将附加后的明文长度分成32位的块
        N = len(additional_message_length_result) // 32
        
        for block in range(N // 16):
            #在列表blocks中将明文分成16个32位的块
            start = block * 512
            blocks = [additional_message_length_result[start + (x * 32) :
				 start + (x * 32) + 32] for x in range(16)]
            
            blocks = [int.from_bytes(word.tobytes(), byteorder="little") for word in blocks]
            
            #定义缓冲区
            A = cls.buffers[Buffer.A]
            B = cls.buffers[Buffer.B]
            C = cls.buffers[Buffer.C]
            D = cls.buffers[Buffer.D]

            #4轮处理
            for i in range(4 * 16):
                #1
                if 0 <= i <= 15:
                    k = i
                    s = [7, 12, 17, 22]
                    temp = F(B, C, D)
                #2
                elif 16 <= i <= 31:
                    k = ((5 * i) + 1) % 16
                    s = [5, 9, 14, 20]
                    temp = G(B, C, D)
                #3
                elif 32 <= i <= 47:
                    k = ((3 * i) + 5) % 16
                    s = [4, 11, 16, 23]
                    temp = H(B, C, D)
                #4
                elif 48 <= i <= 63:
                    k = (7 * i) % 16
                    s = [6, 10, 15, 21]
                    temp = I(B, C, D)

                #执行循环左移与模加
                temp = mod_add(temp, blocks[k])
                temp = mod_add(temp, T[i])
                temp = mod_add(temp, A)
                temp = ROL(temp, s[i % 4])
                temp = mod_add(temp, B)
                
                #下一轮操作
                A = D
                D = C
                C = B
                B = temp

            #更新缓冲区
            cls.buffers[Buffer.A] = mod_add(cls.buffers[Buffer.A], A)
            cls.buffers[Buffer.B] = mod_add(cls.buffers[Buffer.B], B)
            cls.buffers[Buffer.C] = mod_add(cls.buffers[Buffer.C], C)
            cls.buffers[Buffer.D] = mod_add(cls.buffers[Buffer.D], D)

    @classmethod
    #输出
    def Output(cls):
        A = struct.unpack("<I", struct.pack(">I", cls.buffers[Buffer.A]))[0]
        B = struct.unpack("<I", struct.pack(">I", cls.buffers[Buffer.B]))[0]
        C = struct.unpack("<I", struct.pack(">I", cls.buffers[Buffer.C]))[0]
        D = struct.unpack("<I", struct.pack(">I", cls.buffers[Buffer.D]))[0]
        
        #输出缓冲区
        return f"{format(A, '08x')}{format(B, '08x')}{format(C, '08x')}{format(D, '08x')}"
        
    @classmethod
    #压缩函数
    def MyHash(cls, string_M):
        cls.string_M = string_M
        preprocessed_bit_array = cls.additional_message_length(cls.message_fill())
        cls.buffer_initialize()
        cls.message_handing(preprocessed_bit_array)
        return cls.Output()
  

三、RSA签名

my_RSA.py:

# -- coding: gb2312 --

p = 106697219132480173106064317148705638676529121742557567770857687729397446898790451577487723991083173010242416863238099716044775658681981821407922722052778958942891831033512463262741053961681512908218003840408526915629689432111480588966800949428079015682624591636010678691927285321708935076221951173426894836169
q = 144819424465842307806353672547344125290716753535239658417883828941232509622838692761917211806963011168822281666033695157426515864265527046213326145174398018859056439431422867957079149967592078894410082695714160599647180947207504108618794637872261572262805565517756922288320779308895819726074229154002310375209

#扩展欧几里得算法
def extend_gcd(a, b):
    if b == 0:
        return 1, 0, a
    else:
        x, y, r = extend_gcd(b, a % b)
        x, y = y, (x - (a // b) * y)
        return x, y, r
        
#公钥
def generate_publickey():
    n=p*q
    e=65537 #e取固定值
    return e,n
    
#私钥
def generate_privatekey():
	ph_n=(p-1)*(q-1)
	e=65537
	(x, y, r) = extend_gcd(ph_n, e)
	if y<0:
		d = y + ph_n  #直接用加法比%效率要高
	else:
		d = y
	n=p*q
	return d,n
	
#私钥签名
def signature(HM):
    HM=int(HM,16)
    d,n=generate_privatekey()
    print('RSA私钥(d,n):\n'+str(d)+' , '+str(n)+'\n')
    signature_HM=pow(HM,d,n)
    signature_HM=hex(signature_HM)[2:]
    
    return signature_HM
    
#公钥验证
def verify(signature_HM):
	signature_HM=int(signature_HM,16)
	e,n=generate_publickey()
	print('RSA公钥(e,n):\n'+str(e)+' , '+str(n)+'\n')
	HM=pow(signature_HM,e,n)
	HM=hex(HM)[2:]
	
	return HM
 

四、DES算法

my_DES.py:

# -- coding: gb2312 --
import re

#初始置换IP
IP = [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_reverse = [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
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
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盒
S =[
	#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],
]

#置换选择1
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]
        
#置换选择2
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 str2bin(message):
    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

#二进制转化为字符串
def bin2str(bin_str):
    res = ""
    tmp = re.findall(r'.{8}',bin_str)
    for i in tmp:
        res += chr(int(i,2))
    return res

#IP盒处理
def ip_change(bin_str):
    res = ""
    for i in IP:
        res += bin_str[i-1] #数组下标i-1
    return res

#IP逆盒处理
def ip_re_change(bin_str):
    res = ""
    for i in IP_reverse:
        res += bin_str[i-1]
    return res

#E盒处理
def e_key(bin_str):
    res = ""
    for i in E:
        res += bin_str[i-1]
    return res

#字符串异或操作
def str_xor(my_str1,my_str2):
    res = ""
    for i in range(0,len(my_str1)):
		#变成10进制是转化成字符串 2进制与10进制异或结果一样,都是1,0
        xor_res = int(my_str1[i],10)^int(my_str2[i],10)
        if xor_res == 1:
            res += '1'
        if xor_res == 0:
            res += '0'
    return res

#循环左移操作
def ROL(my_str,num):
    left_res = my_str[num:len(my_str)]
    left_res = my_str[0:num]+left_res
    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

# S盒代换
def s_box(my_str):
    res = ""
    c = 0
    for i in range(0,len(my_str),6):
        now_str = my_str[i:i+6]
        row = int(now_str[0]+now_str[5],2)
        col = int(now_str[1:5],2)
        #利用了bin输出有可能不是4位str类型的值,所以才有下面的循环并且加上字符0
        num = bin(S[c][row*16 + col])[2:]   
        for gz in range(0,4-len(num)):
            num = '0'+ num
        res += num
        c  += 1
    return res

#P盒置换
def p_box(bin_str):
    res = ""
    for i in  P:
        res += bin_str[i-1]
    return res

#F函数
def fun_F(bin_str,key):
    first_output = e_key(bin_str)
    second_output = str_xor(first_output,key)
    third_output = s_box(second_output)
    last_output = p_box(third_output)
    
    return last_output

#密钥产生
def generate_key(key):
    key_list = []
    divide_output = change_key1(key)
    key_C0 = divide_output[0:28]
    key_D0 = divide_output[28:]
    for i in SHIFT:
        key_c = ROL(key_C0,i)
        key_d = ROL(key_D0,i)
        key_output = change_key2(key_c + key_d)
        key_list.append(key_output)
        
    return key_list

#64位二进制加密
def des_encrypt_one(bin_message,bin_key): 
    mes_ip_bin = ip_change(bin_message)
    key_lst = generate_key(bin_key)
    mes_left = mes_ip_bin[0:32]
    mes_right = mes_ip_bin[32:]
    
    for i in range(0,15):
        mes_tmp = mes_right
        f_result = fun_F(mes_tmp,key_lst[i])
        mes_right = str_xor(f_result,mes_left)
        mes_left = mes_tmp
    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)
    
    return fin_message

#64位二进制解密
def des_decrypt_one(bin_mess,bin_key):
    mes_ip_bin = ip_change(bin_mess)
    key_lst = generate_key(bin_key)
    lst = range(1,16)
    cipher_left = mes_ip_bin[0:32]
    cipher_right = mes_ip_bin[32:]
    
    for i in lst[::-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
    bin_plain = ip_re_change(fin_output)
    res = bin2str(bin_plain)
    
    return res

#简单判断以及处理信息分组
def deal_mess(bin_mess):
    #param bin_mess: 二进制的信息流
    ans = len(bin_mess)
    if ans % 64 != 0:
        for i in range( 64 - (ans%64)): #不够64位补充0
            bin_mess += '0'
    return bin_mess

#查看秘钥是否为64位
def input_key_judge(bin_key):
    ans = len(bin_key)
    if len(bin_key) < 64:
        if ans % 64 != 0:
            for i in range(64 - (ans % 64)): #不够64位补充0
                bin_key += '0'
    return bin_key

#加密
def DES_encrypt(message,key):
	bin_mess = deal_mess(str2bin(message))
	res = ""
	bin_key = input_key_judge(str2bin(key))
	tmp = re.findall(r'.{64}',bin_mess)
	for i in tmp:
		res += des_encrypt_one(i,bin_key)
	return res

#解密
def DES_decrypt(message,key):
    #bin_mess = deal_mess(str2bin(message))
    bin_mess=message
    res = ""
    bin_key = input_key_judge(str2bin(key))
    tmp = re.findall(r'.{64}',bin_mess)
    for i in tmp:
        res += des_decrypt_one(i,bin_key)
    return res

五、文件安全传输实现

secure_file_transfer.py:

# -- coding: gb2312 --

from my_md5 import MyMd5
from my_RSA import *
from my_DES import *

M="zrx1102"
print("M: "+M+'\n')
len_M=len(M)

#对消息哈希
HM=MyMd5.MyHash(M)
print("Hash(M): "+HM+'\n')

#RSA私钥签名
signature_HM=signature(HM)
print('signature[H(M)]:\n'+signature_HM+'\n')

#消息与签名后的结果链接
link_message=M+'@'+signature_HM
print('M||signature[H(M)]:\n'+link_message+'\n')

#DES加密
key='12345678'
print('DES key: '+key+'\n')
s=DES_encrypt(link_message,key)
print('DES对M||signature[H(M)]加密后的16进制结果:\n'+hex(int(s,2))+'\n')

#DES解密
link_message=DES_decrypt(s,key)
print('DES解密得到M||signature[H(M)]:\n'+link_message+'\n')

#消息拆分
M=link_message[:len_M]
signature_HM=link_message[len_M+1:]
print("拆分后得到的消息M为: ",M,'\n')
print("拆分后得到的signature[H(M)]:\n",signature_HM,'\n')

#RSA公钥验证
HM=verify(signature_HM)
print("对拆分后的数字签名进行RSA公钥验证: "+HM+'\n')

#对拆分后的消息哈希
HM1=MyMd5.MyHash(M)
print("对拆分后的消息M哈希: "+HM1+'\n')

if(HM==HM1):
    print("哈希值相同,文件安全传输成功!")
else:
    print("文件安全传输失败!")
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值