基于Python的非对称加密与对称加密相结合的文件传输系统设计与实现

一、课题名称

基于Python的非对称加密与对称加密相结合的文件传输系统设计与实现

二、课题背景与研究意义

在当前数字信息社会中,文件传输的安全性成为亟需解决的关键问题。尤其在网络环境下,文件在传输过程中可能会被窃听、篡改或伪造,因此如何实现安全、可靠、高效的文件加密传输成为研究热点。

对称加密算法(如AES)具有加密速度快、效率高的优点,但密钥分发困难;非对称加密算法(如RSA)则在密钥交换和身份认证方面具备天然优势,但加解密效率低下。为此,结合非对称加密和对称加密的“混合加密”模式被广泛采用,能够兼顾安全性与性能,已成为实际加密通信系统(如SSL/TLS)的主流结构。

本设计以Python语言为开发平台,设计并实现一个融合RSA与AES算法的文件安全传输系统,具备跨平台性强、结构清晰、用户界面友好等特点,适合教育、企业等多种应用场景,具有良好的学习和实践价值。

三、国内外研究现状

目前主流安全传输协议如HTTPS、SFTP、IPSec等大多采用混合加密机制实现文件传输安全控制。在高校、企业以及开源社区,也有不少关于Python加密传输的项目,但大多缺乏图形界面或结构过于复杂,不适合本科教学与研究。通过本设计,可以将密码学理论与实际编程技能结合,促进应用型人才培养。

四、课题目标与内容

(一)设计目标:

实现一个可运行的文件传输系统,支持局域网内加密传输;
融合非对称加密(RSA)与对称加密(AES)机制;
实现基本的密钥管理、文件加密传输、图形界面交互;
保障数据的机密性、完整性和安全性。

(二)系统功能结构:

密钥管理模块

生成RSA密钥对,用于加密AES密钥;
使用AES密钥对文件数据进行加密/解密;
支持CBC模式加密、PKCS#7填充。

文件传输模块

客户端与服务端基于Socket通信实现文件传输;
客户端加密AES密钥发送,服务端解密并接收文件数据;
支持断开自动关闭连接、异常处理等功能。

图形用户界面(GUI)模块

使用Tkinter实现客户端和服务端界面;
支持文件选择、传输进度条、日志提示;
启动/关闭服务器控制、发送文件操作一键完成。

五、关键技术与实现方法

非对称加密算法(RSA):用于客户端安全地将AES密钥加密并发送给服务端。使用 Cryptodome.PublicKey 实现密钥生成与加密/解密。
对称加密算法(AES):对文件内容进行加密,提升效率。采用CBC模式,确保安全性。
Socket网络编程:使用Python原生socket库,实现客户端-服务端双向通信。
Tkinter图形界面:提升系统易用性,实现用户友好的操作界面。
多线程技术:服务端采用线程并发模型,应对多客户端请求。

六、预期成果

一个完整可运行的Python文件加密传输系统;
RSA/AES加密流程源码与文档;
图形化客户端与服务器界面;
系统说明书、用户手册、测试报告等配套材料;
支持局域网通信、数据安全保护、传输日志打印等功能。

七、研究进度安排

第1-2周查阅资料、确定选题、撰写开题报告

第3-4周搭建基本Socket通信架构、测试连接稳定性

第5-6周实现RSA/AES加密模块、调试加密解密流程

第7-8周实现客户端文件上传与服务端接收逻辑

第9-10周集成图形用户界面(Tkinter)

第11-12周完善异常处理、支持多线程、优化系统性能

第13-14周系统测试、撰写说明书与论文初稿

第15-16周完善论文、准备答辩材料、模拟答辩

八、参考文献

William Stallings.《密码学与网络安全》. 清华大学出版社, 2021
RFC 3447: Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography Specifications
Python官方文档:socket — Low-level networking interface — Python 3.13.5 documentation
PyCryptodome文档:Welcome to PyCryptodome’s documentation — PyCryptodome 3.23.0 documentation
王珊,萨师煊.《数据库系统概论》第5版. 高等教育出版社,2015

核心代码参考案例:

系统概述

本设计实现了一个结合非对称加密(RSA)和对称加密(AES)的文件安全传输系统,兼顾了安全性与性能。系统使用RSA算法进行密钥交换和身份验证,使用AES算法进行高效的文件加密传输。

核心模块设计

1. 密钥管理模块

import os
from Cryptodome.PublicKey import RSA
from Cryptodome.Cipher import PKCS1_OAEP, AES
from Cryptodome.Random import get_random_bytes
import base64
import hashlib

class KeyManager:
    @staticmethod
    def generate_rsa_key_pair(key_size=2048):
        """生成RSA密钥对"""
        key = RSA.generate(key_size)
        private_key = key.export_key()
        public_key = key.publickey().export_key()
        return private_key, public_key
    
    @staticmethod
    def generate_aes_key(key_size=32):
        """生成AES密钥"""
        return get_random_bytes(key_size)
    
    @staticmethod
    def encrypt_with_rsa(public_key, data):
        """使用RSA公钥加密数据"""
        rsa_key = RSA.import_key(public_key)
        cipher_rsa = PKCS1_OAEP.new(rsa_key)
        return cipher_rsa.encrypt(data)
    
    @staticmethod
    def decrypt_with_rsa(private_key, encrypted_data):
        """使用RSA私钥解密数据"""
        rsa_key = RSA.import_key(private_key)
        cipher_rsa = PKCS1_OAEP.new(rsa_key)
        return cipher_rsa.decrypt(encrypted_data)
    
    @staticmethod
    def encrypt_with_aes(key, data):
        """使用AES加密数据"""
        iv = get_random_bytes(AES.block_size)
        cipher_aes = AES.new(key, AES.MODE_CBC, iv)
        encrypted = cipher_aes.encrypt(pad(data, AES.block_size))
        return iv + encrypted
    
    @staticmethod
    def decrypt_with_aes(key, encrypted_data):
        """使用AES解密数据"""
        iv = encrypted_data[:AES.block_size]
        cipher_aes = AES.new(key, AES.MODE_CBC, iv)
        return unpad(cipher_aes.decrypt(encrypted_data[AES.block_size:]), AES.block_size)

def pad(data, block_size):
    """填充数据到块的整数倍"""
    padding_length = block_size - len(data) % block_size
    return data + bytes([padding_length] * padding_length)

def unpad(data, block_size):
    """移除填充数据"""
    padding_length = data[-1]
    return data[:-padding_length]

2. 文件加密传输模块

import socket
import json
from threading import Thread

class FileTransferServer:
    def __init__(self, host='0.0.0.0', port=5000):
        self.host = host
        self.port = port
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.private_key, self.public_key = KeyManager.generate_rsa_key_pair()
        
    def start(self):
        """启动服务器"""
        self.server_socket.bind((self.host, self.port))
        self.server_socket.listen(5)
        print(f"Server listening on {self.host}:{self.port}")
        
        while True:
            client_socket, addr = self.server_socket.accept()
            print(f"Connection from {addr}")
            client_thread = Thread(target=self.handle_client, args=(client_socket,))
            client_thread.start()
    
    def handle_client(self, client_socket):
        """处理客户端连接"""
        try:
            # 1. 发送服务器的公钥给客户端
            client_socket.send(self.public_key)
            
            # 2. 接收客户端使用服务器公钥加密的AES密钥
            encrypted_aes_key = client_socket.recv(2048)
            aes_key = KeyManager.decrypt_with_rsa(self.private_key, encrypted_aes_key)
            
            # 3. 接收加密的文件信息
            encrypted_info = client_socket.recv(1024)
            file_info = json.loads(KeyManager.decrypt_with_aes(aes_key, encrypted_info).decode())
            
            # 4. 接收加密的文件数据
            file_data = b''
            while True:
                chunk = client_socket.recv(4096)
                if not chunk:
                    break
                file_data += chunk
            
            # 5. 解密文件数据
            decrypted_data = KeyManager.decrypt_with_aes(aes_key, file_data)
            
            # 6. 保存文件
            save_path = os.path.join('received_files', file_info['filename'])
            os.makedirs('received_files', exist_ok=True)
            with open(save_path, 'wb') as f:
                f.write(decrypted_data)
            
            print(f"File {file_info['filename']} received and saved successfully.")
            
        except Exception as e:
            print(f"Error handling client: {e}")
        finally:
            client_socket.close()

class FileTransferClient:
    def __init__(self, host='localhost', port=5000):
        self.host = host
        self.port = port
        self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        
    def send_file(self, filepath):
        """发送文件到服务器"""
        try:
            self.client_socket.connect((self.host, self.port))
            
            # 1. 接收服务器的公钥
            server_public_key = self.client_socket.recv(4096)
            
            # 2. 生成AES密钥并用服务器公钥加密
            aes_key = KeyManager.generate_aes_key()
            encrypted_aes_key = KeyManager.encrypt_with_rsa(server_public_key, aes_key)
            self.client_socket.send(encrypted_aes_key)
            
            # 3. 读取并加密文件
            with open(filepath, 'rb') as f:
                file_data = f.read()
            
            filename = os.path.basename(filepath)
            file_info = json.dumps({
                'filename': filename,
                'filesize': len(file_data)
            }).encode()
            
            # 4. 加密文件信息并发送
            encrypted_info = KeyManager.encrypt_with_aes(aes_key, file_info)
            self.client_socket.send(encrypted_info)
            
            # 5. 加密文件数据并发送
            encrypted_data = KeyManager.encrypt_with_aes(aes_key, file_data)
            self.client_socket.sendall(encrypted_data)
            
            print(f"File {filename} sent successfully.")
            
        except Exception as e:
            print(f"Error sending file: {e}")
        finally:
            self.client_socket.close()

3. 用户界面模块

import tkinter as tk
from tkinter import filedialog, messagebox
from tkinter.ttk import Progressbar

class FileTransferGUI:
    def __init__(self, root):
        self.root = root
        root.title("安全文件传输系统")
        root.geometry("500x300")
        
        # 服务器控制区域
        server_frame = tk.LabelFrame(root, text="服务器控制", padx=5, pady=5)
        server_frame.pack(fill="x", padx=10, pady=5)
        
        self.start_server_btn = tk.Button(
            server_frame, text="启动服务器", command=self.start_server)
        self.start_server_btn.pack(side="left", padx=5)
        
        self.stop_server_btn = tk.Button(
            server_frame, text="停止服务器", state="disabled", command=self.stop_server)
        self.stop_server_btn.pack(side="left", padx=5)
        
        # 客户端区域
        client_frame = tk.LabelFrame(root, text="文件传输", padx=5, pady=5)
        client_frame.pack(fill="x", padx=10, pady=5)
        
        self.file_path = tk.StringVar()
        tk.Entry(client_frame, textvariable=self.file_path, width=40).pack(
            side="left", padx=5)
        
        tk.Button(client_frame, text="浏览...", command=self.browse_file).pack(
            side="left", padx=5)
        
        tk.Button(client_frame, text="发送文件", command=self.send_file).pack(
            side="left", padx=5)
        
        # 状态区域
        status_frame = tk.Frame(root)
        status_frame.pack(fill="x", padx=10, pady=5)
        
        self.status_label = tk.Label(status_frame, text="就绪")
        self.status_label.pack(side="left")
        
        self.progress = Progressbar(root, orient="horizontal", 
                                  length=200, mode="determinate")
        self.progress.pack(pady=10)
        
        # 服务器实例
        self.server = None
        self.server_thread = None
    
    def browse_file(self):
        filename = filedialog.askopenfilename()
        if filename:
            self.file_path.set(filename)
    
    def start_server(self):
        self.server = FileTransferServer()
        self.server_thread = Thread(target=self.server.start)
        self.server_thread.daemon = True
        self.server_thread.start()
        
        self.start_server_btn.config(state="disabled")
        self.stop_server_btn.config(state="normal")
        self.status_label.config(text="服务器已启动")
    
    def stop_server(self):
        if self.server:
            self.server.server_socket.close()
        
        self.start_server_btn.config(state="normal")
        self.stop_server_btn.config(state="disabled")
        self.status_label.config(text="服务器已停止")
    
    def send_file(self):
        filepath = self.file_path.get()
        if not filepath:
            messagebox.showerror("错误", "请选择要发送的文件")
            return
        
        client = FileTransferClient()
        Thread(target=client.send_file, args=(filepath,)).start()
        self.status_label.config(text="文件发送中...")
        self.progress["value"] = 0
        
        # 模拟进度条
        for i in range(5):
            self.root.after(i*200, lambda i=i: self.progress.step(20))
        
        self.root.after(1000, lambda: self.status_label.config(text="文件发送完成"))
        self.root.after(1000, lambda: self.progress["value"] = 0)

def main():
    root = tk.Tk()
    app = FileTransferGUI(root)
    root.mainloop()

if __name__ == "__main__":
    main()

系统特点

混合加密机制:结合RSA和AES的优势,RSA用于安全交换AES密钥,AES用于高效加密文件数据
安全性

使用PKCS#1 OAEP填充方案增强RSA安全性
每次会话使用不同的AES密钥
实现CBC模式和适当的填充方案

完整性:通过文件大小验证确保数据传输完整
用户友好:提供图形界面便于操作

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容