diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index a7cdac7..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# 默认忽略的文件 -/shelf/ -/workspace.xml -# 基于编辑器的 HTTP 客户端请求 -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 105ce2d..0000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/material_theme_project_new.xml b/.idea/material_theme_project_new.xml deleted file mode 100644 index 579b55b..0000000 --- a/.idea/material_theme_project_new.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index f8a22e9..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index f51b2be..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/应用密码学课设.iml b/.idea/应用密码学课设.iml deleted file mode 100644 index a80cbb1..0000000 --- a/.idea/应用密码学课设.iml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/1.txt b/1.txt new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/1.txt @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/encryption_utils.py b/encryption_utils.py index 92f0d6b..4a916a7 100644 --- a/encryption_utils.py +++ b/encryption_utils.py @@ -1,6 +1,7 @@ from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_OAEP, AES from Crypto.Random import get_random_bytes +from Crypto.Signature import pkcs1_15 from Crypto.Hash import SHA256 class AsymmetricEncryption: @@ -21,6 +22,19 @@ class AsymmetricEncryption: cipher_rsa = PKCS1_OAEP.new(self.key_pair) return cipher_rsa.decrypt(encrypted_data) + def sign_data(self, data): + h = SHA256.new(data) + signature = pkcs1_15.new(self.key_pair).sign(h) + return signature + + def verify_signature(self, data, signature, public_key): + h = SHA256.new(data) + try: + pkcs1_15.new(public_key).verify(h, signature) + return True + except (ValueError, TypeError): + return False + class SymmetricEncryption: def encrypt(self, data, key): cipher_aes = AES.new(key, AES.MODE_GCM) @@ -30,8 +44,4 @@ class SymmetricEncryption: def decrypt(self, nonce, ciphertext, tag, key): cipher_aes = AES.new(key, AES.MODE_GCM, nonce=nonce) - return cipher_aes.decrypt_and_verify(ciphertext, tag) - -def calculate_file_hash(file_data): - hash_obj = SHA256.new(file_data) - return hash_obj.digest() + return cipher_aes.decrypt_and_verify(ciphertext, tag) \ No newline at end of file diff --git a/example.txt b/example.txt deleted file mode 100644 index 76b02a3..0000000 --- a/example.txt +++ /dev/null @@ -1,2 +0,0 @@ -123456 -asdfghjkl \ No newline at end of file diff --git a/file_transfer.py b/file_transfer.py index 7100c26..2c9bfaa 100644 --- a/file_transfer.py +++ b/file_transfer.py @@ -1,15 +1,14 @@ import socket import threading from Crypto.PublicKey import RSA -from Crypto.Cipher import AES, PKCS1_OAEP -from Crypto.Random import get_random_bytes -from Crypto.Hash import SHA256 - +from sender import Sender +from receiver import Receiver class FileTransferApp: - def __init__(self, host, port): + def __init__(self, host, port, role): self.host = host self.port = port + self.role = role self.private_key = None self.public_key = None self.running = True @@ -18,55 +17,114 @@ class FileTransferApp: key = RSA.generate(2048) self.private_key = key.export_key() self.public_key = key.publickey().export_key() - print("密钥生成成功。") + if self.role == 'sender': + priv_filename = 'send_private.pem' + pub_filename = 'send_public.pem' + else: + priv_filename = 'receive_private.pem' + pub_filename = 'receive_public.pem' + with open(priv_filename, 'wb') as priv_file: + priv_file.write(self.private_key) + with open(pub_filename, 'wb') as pub_file: + pub_file.write(self.public_key) + print(f"密钥生成成功,已保存到 {priv_filename} 和 {pub_filename}。") + + def load_keys(self): + if self.role == 'sender': + priv_filename = 'send_private.pem' + pub_filename = 'send_public.pem' + else: + priv_filename = 'receive_private.pem' + pub_filename = 'receive_public.pem' + try: + with open(priv_filename, 'rb') as priv_file: + self.private_key = priv_file.read() + with open(pub_filename, 'rb') as pub_file: + self.public_key = pub_file.read() + print("密钥加载成功。") + except FileNotFoundError: + print("密钥文件未找到,请先生成密钥。") + + def load_public_key(self, filepath): + try: + with open(filepath, 'rb') as pub_file: + return pub_file.read() + except FileNotFoundError: + print(f"公钥文件 {filepath} 未找到。") + return None + + def send_file(self, filepath, receiver_host, receiver_public_key_path): + receiver_public_key = self.load_public_key(receiver_public_key_path) + if receiver_public_key is None: + return - def send_file(self, filepath, receiver_host): try: with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((receiver_host, self.port)) - sender = Sender(filepath, receiver_public_key=self.public_key) + + sender = Sender(filepath, receiver_public_key, self.private_key) data_to_send = sender.send_file() - s.sendall(data_to_send) + if data_to_send is None: + print("文件加密失败,未发送。") + return + + s.sendall(data_to_send.encode()) print("文件发送成功。") except Exception as e: print(f"发送文件时发生错误: {e}") - def receive_file(self): + def receive_file(self, sender_public_key_path): + sender_public_key = self.load_public_key(sender_public_key_path) + if sender_public_key is None: + return + try: + if self.private_key is None: + raise ValueError("未生成私钥,请先生成密钥。") + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((self.host, self.port)) s.listen() - print(f"服务器正在监听 {self.host}:{self.port}") + print(f"服务器正在 {self.host}:{self.port} 监听...") conn, addr = s.accept() with conn: - print(f"已连接 {addr}") + print(f"已连接到 {addr}") data = b'' while True: packet = conn.recv(1024) if not packet: break data += packet - receiver = Receiver(private_key=self.private_key) - decrypted_data = receiver.receive_file(data) - if decrypted_data: - # 保存或处理解密后的文件数据 + + receiver = Receiver(self.private_key, sender_public_key) + decrypted_data = receiver.receive_file(data.decode()) + + if decrypted_data is not None: with open('received_file', 'wb') as f: f.write(decrypted_data) print("文件接收并解密成功。") + else: + print("解密失败,文件未保存。") + except ValueError as ve: + print(f"值错误: {ve}") except Exception as e: print(f"接收文件时发生错误: {e}") def run(self): while self.running: - command = input("输入 'generate_keys' 生成密钥,'send' 发送文件,'receive' 接收文件,或 'exit' 退出程序: ").strip().lower() + command = input("输入 'generate_keys' 生成密钥,'load_keys' 加载密钥,'send' 发送文件,'receive' 接收文件,或 'exit' 退出程序: ").strip().lower() if command == 'generate_keys': self.generate_keys() + elif command == 'load_keys': + self.load_keys() elif command == 'send': filepath = input("输入要发送的文件路径: ") receiver_host = input("输入接收方的计算机IP地址: ") - threading.Thread(target=self.send_file, args=(filepath, receiver_host)).start() + receiver_public_key_path = input("输入接收方的公钥文件路径: ") + threading.Thread(target=self.send_file, args=(filepath, receiver_host, receiver_public_key_path)).start() elif command == 'receive': - threading.Thread(target=self.receive_file).start() + sender_public_key_path = input("输入发送方的公钥文件路径: ") + threading.Thread(target=self.receive_file, args=(sender_public_key_path,)).start() elif command == 'exit': self.running = False print("正在退出程序。") @@ -75,5 +133,6 @@ class FileTransferApp: print("无效的命令。") if __name__ == "__main__": - app = FileTransferApp(host='0.0.0.0', port=65432) - app.run() + role = input("输入角色 ('sender' 或 'receiver'): ").strip().lower() + app = FileTransferApp(host='0.0.0.0', port=65432, role=role) + app.run() \ No newline at end of file diff --git a/receiver.py b/receiver.py index 9ed9cf5..2865b7c 100644 --- a/receiver.py +++ b/receiver.py @@ -1,31 +1,30 @@ +from Crypto.Cipher import AES, PKCS1_OAEP +from Crypto.PublicKey import RSA +import json import base64 -from encryption_utils import SymmetricEncryption, AsymmetricEncryption, calculate_file_hash +from encryption_utils import AsymmetricEncryption, SymmetricEncryption class Receiver: - def __init__(self, private_key): - self.private_key = private_key - - def receive_file(self, encoded_data_packet): - decoded_data_packet = base64.b64decode(encoded_data_packet) - - nonce = decoded_data_packet[:16] - ciphertext = decoded_data_packet[16:-256-64] - tag = decoded_data_packet[-256-64:-256] - encrypted_symmetric_key = decoded_data_packet[-256:] - original_hash = decoded_data_packet[-256-64:-256] # 保持为字节 - - asymmetric_encryption = AsymmetricEncryption() - decrypted_symmetric_key = asymmetric_encryption.decrypt_with_private_key(encrypted_symmetric_key) - - symmetric_encryption = SymmetricEncryption() - decrypted_file_data = symmetric_encryption.decrypt(nonce, ciphertext, tag, decrypted_symmetric_key) - - # Recalculate hash of decrypted file data - received_file_hash = calculate_file_hash(decrypted_file_data).encode() - - if received_file_hash == original_hash: - print("文件传输成功,文件完整性验证通过。") + def __init__(self, private_key, sender_public_key): + self.private_key = RSA.import_key(private_key) + self.sender_public_key = RSA.import_key(sender_public_key) + self.asym_enc = AsymmetricEncryption() + self.sym_enc = SymmetricEncryption() + + def receive_file(self, data): + data = json.loads(data) + enc_session_key = base64.b64decode(data['enc_session_key']) + nonce = base64.b64decode(data['nonce']) + tag = base64.b64decode(data['tag']) + ciphertext = base64.b64decode(data['ciphertext']) + signature = base64.b64decode(data['signature']) + + cipher_rsa = PKCS1_OAEP.new(self.private_key) + session_key = cipher_rsa.decrypt(enc_session_key) + + file_data = self.sym_enc.decrypt(nonce, ciphertext, tag, session_key) + + if self.asym_enc.verify_signature(file_data, signature, self.sender_public_key): + return file_data else: - print("文件传输失败,文件可能已被篡改。") - - return decrypted_file_data + raise ValueError("签名验证失败") \ No newline at end of file diff --git a/run_example.py b/run_example.py index 520728a..2c9bfaa 100644 --- a/run_example.py +++ b/run_example.py @@ -1,35 +1,138 @@ -from encryption_utils import AsymmetricEncryption, SymmetricEncryption -from Crypto.Random import get_random_bytes +import socket +import threading +from Crypto.PublicKey import RSA +from sender import Sender +from receiver import Receiver -def run_example(): - # 生成接收方的密钥对 - receiver_asymmetric = AsymmetricEncryption() - receiver_public_key = receiver_asymmetric.get_public_key() - receiver_private_key = receiver_asymmetric.get_private_key() +class FileTransferApp: + def __init__(self, host, port, role): + self.host = host + self.port = port + self.role = role + self.private_key = None + self.public_key = None + self.running = True - # 生成对称密钥 - symmetric_key = get_random_bytes(16) # AES 128 位密钥 + def generate_keys(self): + key = RSA.generate(2048) + self.private_key = key.export_key() + self.public_key = key.publickey().export_key() + if self.role == 'sender': + priv_filename = 'send_private.pem' + pub_filename = 'send_public.pem' + else: + priv_filename = 'receive_private.pem' + pub_filename = 'receive_public.pem' + with open(priv_filename, 'wb') as priv_file: + priv_file.write(self.private_key) + with open(pub_filename, 'wb') as pub_file: + pub_file.write(self.public_key) + print(f"密钥生成成功,已保存到 {priv_filename} 和 {pub_filename}。") - # 使用接收方的公钥加密对称密钥 - encrypted_symmetric_key = receiver_asymmetric.encrypt_with_public_key(symmetric_key, receiver_public_key) + def load_keys(self): + if self.role == 'sender': + priv_filename = 'send_private.pem' + pub_filename = 'send_public.pem' + else: + priv_filename = 'receive_private.pem' + pub_filename = 'receive_public.pem' + try: + with open(priv_filename, 'rb') as priv_file: + self.private_key = priv_file.read() + with open(pub_filename, 'rb') as pub_file: + self.public_key = pub_file.read() + print("密钥加载成功。") + except FileNotFoundError: + print("密钥文件未找到,请先生成密钥。") - # 读取文件内容 - with open('example.txt', 'rb') as file: - file_data = file.read() + def load_public_key(self, filepath): + try: + with open(filepath, 'rb') as pub_file: + return pub_file.read() + except FileNotFoundError: + print(f"公钥文件 {filepath} 未找到。") + return None - # 使用对称密钥加密文件内容 - symmetric_encryption = SymmetricEncryption() - nonce, ciphertext, tag = symmetric_encryption.encrypt(file_data, symmetric_key) + def send_file(self, filepath, receiver_host, receiver_public_key_path): + receiver_public_key = self.load_public_key(receiver_public_key_path) + if receiver_public_key is None: + return - # 模拟发送和接收 - encoded_packet = (encrypted_symmetric_key, nonce, ciphertext, tag) + try: + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.connect((receiver_host, self.port)) - # 使用接收方私钥解密对称密钥 - decrypted_symmetric_key = receiver_asymmetric.decrypt_with_private_key(encoded_packet[0]) + sender = Sender(filepath, receiver_public_key, self.private_key) + data_to_send = sender.send_file() + if data_to_send is None: + print("文件加密失败,未发送。") + return - # 使用解密后的对称密钥解密文件内容 - decrypted_data = symmetric_encryption.decrypt(encoded_packet[1], encoded_packet[2], encoded_packet[3], decrypted_symmetric_key) - print("Decrypted Data:", decrypted_data.decode('utf-8')) + s.sendall(data_to_send.encode()) + print("文件发送成功。") + except Exception as e: + print(f"发送文件时发生错误: {e}") + + def receive_file(self, sender_public_key_path): + sender_public_key = self.load_public_key(sender_public_key_path) + if sender_public_key is None: + return + + try: + if self.private_key is None: + raise ValueError("未生成私钥,请先生成密钥。") + + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.bind((self.host, self.port)) + s.listen() + print(f"服务器正在 {self.host}:{self.port} 监听...") + conn, addr = s.accept() + with conn: + print(f"已连接到 {addr}") + data = b'' + while True: + packet = conn.recv(1024) + if not packet: + break + data += packet + + receiver = Receiver(self.private_key, sender_public_key) + decrypted_data = receiver.receive_file(data.decode()) + + if decrypted_data is not None: + with open('received_file', 'wb') as f: + f.write(decrypted_data) + print("文件接收并解密成功。") + else: + print("解密失败,文件未保存。") + except ValueError as ve: + print(f"值错误: {ve}") + except Exception as e: + print(f"接收文件时发生错误: {e}") + + def run(self): + while self.running: + command = input("输入 'generate_keys' 生成密钥,'load_keys' 加载密钥,'send' 发送文件,'receive' 接收文件,或 'exit' 退出程序: ").strip().lower() + if command == 'generate_keys': + self.generate_keys() + elif command == 'load_keys': + self.load_keys() + elif command == 'send': + filepath = input("输入要发送的文件路径: ") + receiver_host = input("输入接收方的计算机IP地址: ") + receiver_public_key_path = input("输入接收方的公钥文件路径: ") + threading.Thread(target=self.send_file, args=(filepath, receiver_host, receiver_public_key_path)).start() + elif command == 'receive': + sender_public_key_path = input("输入发送方的公钥文件路径: ") + threading.Thread(target=self.receive_file, args=(sender_public_key_path,)).start() + elif command == 'exit': + self.running = False + print("正在退出程序。") + break + else: + print("无效的命令。") if __name__ == "__main__": - run_example() + role = input("输入角色 ('sender' 或 'receiver'): ").strip().lower() + app = FileTransferApp(host='0.0.0.0', port=65432, role=role) + app.run() \ No newline at end of file diff --git a/sender.py b/sender.py index afcb64d..4ac039a 100644 --- a/sender.py +++ b/sender.py @@ -1,25 +1,35 @@ +from Crypto.Cipher import AES, PKCS1_OAEP +from Crypto.Random import get_random_bytes +from Crypto.PublicKey import RSA +import json import base64 -from Crypto.Random import get_random_bytes # 确保导入随机字节生成函数 -from encryption_utils import SymmetricEncryption, AsymmetricEncryption, calculate_file_hash +from encryption_utils import AsymmetricEncryption, SymmetricEncryption class Sender: - def __init__(self, filepath, receiver_public_key): + def __init__(self, filepath, receiver_public_key, sender_private_key): self.filepath = filepath - self.receiver_public_key = receiver_public_key + self.receiver_public_key = RSA.import_key(receiver_public_key) + self.sender_private_key = RSA.import_key(sender_private_key) + self.asym_enc = AsymmetricEncryption() + self.sym_enc = SymmetricEncryption() def send_file(self): with open(self.filepath, 'rb') as f: file_data = f.read() - symmetric_key = get_random_bytes(16) - symmetric_encryption = SymmetricEncryption() - nonce, ciphertext, tag = symmetric_encryption.encrypt(file_data, symmetric_key) + session_key = get_random_bytes(16) + cipher_rsa = PKCS1_OAEP.new(self.receiver_public_key) + enc_session_key = cipher_rsa.encrypt(session_key) - file_hash = calculate_file_hash(file_data) + nonce, ciphertext, tag = self.sym_enc.encrypt(file_data, session_key) + signature = self.asym_enc.sign_data(file_data) - asymmetric_encryption = AsymmetricEncryption() - encrypted_symmetric_key = asymmetric_encryption.encrypt_with_public_key(symmetric_key, self.receiver_public_key) + data_to_send = { + 'enc_session_key': base64.b64encode(enc_session_key).decode(), + 'nonce': base64.b64encode(nonce).decode(), + 'tag': base64.b64encode(tag).decode(), + 'ciphertext': base64.b64encode(ciphertext).decode(), + 'signature': base64.b64encode(signature).decode() + } - encoded_data_packet = base64.b64encode(nonce + ciphertext + tag + encrypted_symmetric_key + file_hash.encode()) - - return encoded_data_packet + return json.dumps(data_to_send) \ No newline at end of file