main
Mming-145460 8 months ago
parent 97b858b2f5
commit ba2dd4c682

3
.idea/.gitignore vendored

@ -0,0 +1,3 @@
# 默认忽略的文件
/shelf/
/workspace.xml

@ -0,0 +1 @@
GUI.py

@ -0,0 +1,400 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DBNavigator.Project.DatabaseFileManager">
<open-files />
</component>
<component name="DBNavigator.Project.Settings">
<connections />
<browser-settings>
<general>
<display-mode value="TABBED" />
<navigation-history-size value="100" />
<show-object-details value="false" />
<enable-sticky-paths value="true" />
</general>
<filters>
<object-type-filter>
<object-type name="SCHEMA" enabled="true" />
<object-type name="USER" enabled="true" />
<object-type name="ROLE" enabled="true" />
<object-type name="PRIVILEGE" enabled="true" />
<object-type name="CHARSET" enabled="true" />
<object-type name="TABLE" enabled="true" />
<object-type name="VIEW" enabled="true" />
<object-type name="MATERIALIZED_VIEW" enabled="true" />
<object-type name="NESTED_TABLE" enabled="true" />
<object-type name="COLUMN" enabled="true" />
<object-type name="INDEX" enabled="true" />
<object-type name="CONSTRAINT" enabled="true" />
<object-type name="DATASET_TRIGGER" enabled="true" />
<object-type name="DATABASE_TRIGGER" enabled="true" />
<object-type name="SYNONYM" enabled="true" />
<object-type name="SEQUENCE" enabled="true" />
<object-type name="PROCEDURE" enabled="true" />
<object-type name="FUNCTION" enabled="true" />
<object-type name="PACKAGE" enabled="true" />
<object-type name="TYPE" enabled="true" />
<object-type name="TYPE_ATTRIBUTE" enabled="true" />
<object-type name="ARGUMENT" enabled="true" />
<object-type name="DIMENSION" enabled="true" />
<object-type name="CLUSTER" enabled="true" />
<object-type name="DBLINK" enabled="true" />
</object-type-filter>
</filters>
<sorting>
<object-type name="COLUMN" sorting-type="NAME" />
<object-type name="FUNCTION" sorting-type="NAME" />
<object-type name="PROCEDURE" sorting-type="NAME" />
<object-type name="ARGUMENT" sorting-type="POSITION" />
<object-type name="TYPE ATTRIBUTE" sorting-type="POSITION" />
</sorting>
<default-editors>
<object-type name="VIEW" editor-type="SELECTION" />
<object-type name="PACKAGE" editor-type="SELECTION" />
<object-type name="TYPE" editor-type="SELECTION" />
</default-editors>
</browser-settings>
<navigation-settings>
<lookup-filters>
<lookup-objects>
<object-type name="SCHEMA" enabled="true" />
<object-type name="USER" enabled="false" />
<object-type name="ROLE" enabled="false" />
<object-type name="PRIVILEGE" enabled="false" />
<object-type name="CHARSET" enabled="false" />
<object-type name="TABLE" enabled="true" />
<object-type name="VIEW" enabled="true" />
<object-type name="MATERIALIZED VIEW" enabled="true" />
<object-type name="INDEX" enabled="true" />
<object-type name="CONSTRAINT" enabled="true" />
<object-type name="DATASET TRIGGER" enabled="true" />
<object-type name="DATABASE TRIGGER" enabled="true" />
<object-type name="SYNONYM" enabled="false" />
<object-type name="SEQUENCE" enabled="true" />
<object-type name="PROCEDURE" enabled="true" />
<object-type name="FUNCTION" enabled="true" />
<object-type name="PACKAGE" enabled="true" />
<object-type name="TYPE" enabled="true" />
<object-type name="DIMENSION" enabled="false" />
<object-type name="CLUSTER" enabled="false" />
<object-type name="DBLINK" enabled="true" />
</lookup-objects>
<force-database-load value="false" />
<prompt-connection-selection value="true" />
<prompt-schema-selection value="true" />
</lookup-filters>
</navigation-settings>
<dataset-grid-settings>
<general>
<enable-zooming value="true" />
<enable-column-tooltip value="true" />
</general>
<sorting>
<nulls-first value="true" />
<max-sorting-columns value="4" />
</sorting>
<audit-columns>
<column-names value="" />
<visible value="true" />
<editable value="false" />
</audit-columns>
</dataset-grid-settings>
<dataset-editor-settings>
<text-editor-popup>
<active value="false" />
<active-if-empty value="false" />
<data-length-threshold value="100" />
<popup-delay value="1000" />
</text-editor-popup>
<values-actions-popup>
<show-popup-button value="true" />
<element-count-threshold value="1000" />
<data-length-threshold value="250" />
</values-actions-popup>
<general>
<fetch-block-size value="100" />
<fetch-timeout value="30" />
<trim-whitespaces value="true" />
<convert-empty-strings-to-null value="true" />
<select-content-on-cell-edit value="true" />
<large-value-preview-active value="true" />
</general>
<filters>
<prompt-filter-dialog value="true" />
<default-filter-type value="BASIC" />
</filters>
<qualified-text-editor text-length-threshold="300">
<content-types>
<content-type name="Text" enabled="true" />
<content-type name="Properties" enabled="true" />
<content-type name="XML" enabled="true" />
<content-type name="DTD" enabled="true" />
<content-type name="HTML" enabled="true" />
<content-type name="XHTML" enabled="true" />
<content-type name="SQL" enabled="true" />
<content-type name="PL/SQL" enabled="true" />
<content-type name="JSON" enabled="true" />
<content-type name="JSON5" enabled="true" />
<content-type name="YAML" enabled="true" />
</content-types>
</qualified-text-editor>
<record-navigation>
<navigation-target value="VIEWER" />
</record-navigation>
</dataset-editor-settings>
<code-editor-settings>
<general>
<show-object-navigation-gutter value="false" />
<show-spec-declaration-navigation-gutter value="true" />
<enable-spellchecking value="true" />
<enable-reference-spellchecking value="false" />
</general>
<confirmations>
<save-changes value="false" />
<revert-changes value="true" />
<exit-on-changes value="ASK" />
</confirmations>
</code-editor-settings>
<code-completion-settings>
<filters>
<basic-filter>
<filter-element type="RESERVED_WORD" id="keyword" selected="true" />
<filter-element type="RESERVED_WORD" id="function" selected="true" />
<filter-element type="RESERVED_WORD" id="parameter" selected="true" />
<filter-element type="RESERVED_WORD" id="datatype" selected="true" />
<filter-element type="RESERVED_WORD" id="exception" selected="true" />
<filter-element type="OBJECT" id="schema" selected="true" />
<filter-element type="OBJECT" id="role" selected="true" />
<filter-element type="OBJECT" id="user" selected="true" />
<filter-element type="OBJECT" id="privilege" selected="true" />
<user-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="false" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</user-schema>
<public-schema>
<filter-element type="OBJECT" id="table" selected="false" />
<filter-element type="OBJECT" id="view" selected="false" />
<filter-element type="OBJECT" id="materialized view" selected="false" />
<filter-element type="OBJECT" id="index" selected="false" />
<filter-element type="OBJECT" id="constraint" selected="false" />
<filter-element type="OBJECT" id="trigger" selected="false" />
<filter-element type="OBJECT" id="synonym" selected="false" />
<filter-element type="OBJECT" id="sequence" selected="false" />
<filter-element type="OBJECT" id="procedure" selected="false" />
<filter-element type="OBJECT" id="function" selected="false" />
<filter-element type="OBJECT" id="package" selected="false" />
<filter-element type="OBJECT" id="type" selected="false" />
<filter-element type="OBJECT" id="dimension" selected="false" />
<filter-element type="OBJECT" id="cluster" selected="false" />
<filter-element type="OBJECT" id="dblink" selected="false" />
</public-schema>
<any-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</any-schema>
</basic-filter>
<extended-filter>
<filter-element type="RESERVED_WORD" id="keyword" selected="true" />
<filter-element type="RESERVED_WORD" id="function" selected="true" />
<filter-element type="RESERVED_WORD" id="parameter" selected="true" />
<filter-element type="RESERVED_WORD" id="datatype" selected="true" />
<filter-element type="RESERVED_WORD" id="exception" selected="true" />
<filter-element type="OBJECT" id="schema" selected="true" />
<filter-element type="OBJECT" id="user" selected="true" />
<filter-element type="OBJECT" id="role" selected="true" />
<filter-element type="OBJECT" id="privilege" selected="true" />
<user-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</user-schema>
<public-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</public-schema>
<any-schema>
<filter-element type="OBJECT" id="table" selected="true" />
<filter-element type="OBJECT" id="view" selected="true" />
<filter-element type="OBJECT" id="materialized view" selected="true" />
<filter-element type="OBJECT" id="index" selected="true" />
<filter-element type="OBJECT" id="constraint" selected="true" />
<filter-element type="OBJECT" id="trigger" selected="true" />
<filter-element type="OBJECT" id="synonym" selected="true" />
<filter-element type="OBJECT" id="sequence" selected="true" />
<filter-element type="OBJECT" id="procedure" selected="true" />
<filter-element type="OBJECT" id="function" selected="true" />
<filter-element type="OBJECT" id="package" selected="true" />
<filter-element type="OBJECT" id="type" selected="true" />
<filter-element type="OBJECT" id="dimension" selected="true" />
<filter-element type="OBJECT" id="cluster" selected="true" />
<filter-element type="OBJECT" id="dblink" selected="true" />
</any-schema>
</extended-filter>
</filters>
<sorting enabled="true">
<sorting-element type="RESERVED_WORD" id="keyword" />
<sorting-element type="RESERVED_WORD" id="datatype" />
<sorting-element type="OBJECT" id="column" />
<sorting-element type="OBJECT" id="table" />
<sorting-element type="OBJECT" id="view" />
<sorting-element type="OBJECT" id="materialized view" />
<sorting-element type="OBJECT" id="index" />
<sorting-element type="OBJECT" id="constraint" />
<sorting-element type="OBJECT" id="trigger" />
<sorting-element type="OBJECT" id="synonym" />
<sorting-element type="OBJECT" id="sequence" />
<sorting-element type="OBJECT" id="procedure" />
<sorting-element type="OBJECT" id="function" />
<sorting-element type="OBJECT" id="package" />
<sorting-element type="OBJECT" id="type" />
<sorting-element type="OBJECT" id="dimension" />
<sorting-element type="OBJECT" id="cluster" />
<sorting-element type="OBJECT" id="dblink" />
<sorting-element type="OBJECT" id="schema" />
<sorting-element type="OBJECT" id="role" />
<sorting-element type="OBJECT" id="user" />
<sorting-element type="RESERVED_WORD" id="function" />
<sorting-element type="RESERVED_WORD" id="parameter" />
</sorting>
<format>
<enforce-code-style-case value="true" />
</format>
</code-completion-settings>
<execution-engine-settings>
<statement-execution>
<fetch-block-size value="100" />
<execution-timeout value="20" />
<debug-execution-timeout value="600" />
<focus-result value="false" />
<prompt-execution value="false" />
</statement-execution>
<script-execution>
<command-line-interfaces />
<execution-timeout value="300" />
</script-execution>
<method-execution>
<execution-timeout value="30" />
<debug-execution-timeout value="600" />
<parameter-history-size value="10" />
</method-execution>
</execution-engine-settings>
<operation-settings>
<transactions>
<uncommitted-changes>
<on-project-close value="ASK" />
<on-disconnect value="ASK" />
<on-autocommit-toggle value="ASK" />
</uncommitted-changes>
<multiple-uncommitted-changes>
<on-commit value="ASK" />
<on-rollback value="ASK" />
</multiple-uncommitted-changes>
</transactions>
<session-browser>
<disconnect-session value="ASK" />
<kill-session value="ASK" />
<reload-on-filter-change value="false" />
</session-browser>
<compiler>
<compile-type value="KEEP" />
<compile-dependencies value="ASK" />
<always-show-controls value="false" />
</compiler>
</operation-settings>
<ddl-file-settings>
<extensions>
<mapping file-type-id="VIEW" extensions="vw" />
<mapping file-type-id="TRIGGER" extensions="trg" />
<mapping file-type-id="PROCEDURE" extensions="prc" />
<mapping file-type-id="FUNCTION" extensions="fnc" />
<mapping file-type-id="PACKAGE" extensions="pkg" />
<mapping file-type-id="PACKAGE_SPEC" extensions="pks" />
<mapping file-type-id="PACKAGE_BODY" extensions="pkb" />
<mapping file-type-id="TYPE" extensions="tpe" />
<mapping file-type-id="TYPE_SPEC" extensions="tps" />
<mapping file-type-id="TYPE_BODY" extensions="tpb" />
</extensions>
<general>
<lookup-ddl-files value="true" />
<create-ddl-files value="false" />
<synchronize-ddl-files value="true" />
<use-qualified-names value="false" />
<make-scripts-rerunnable value="true" />
</general>
</ddl-file-settings>
<general-settings>
<regional-settings>
<date-format value="MEDIUM" />
<number-format value="UNGROUPED" />
<locale value="SYSTEM_DEFAULT" />
<use-custom-formats value="false" />
</regional-settings>
<environment>
<environment-types>
<environment-type id="development" name="Development" description="Development environment" color="-2430209/-12296320" readonly-code="false" readonly-data="false" />
<environment-type id="integration" name="Integration" description="Integration environment" color="-2621494/-12163514" readonly-code="true" readonly-data="false" />
<environment-type id="production" name="Production" description="Productive environment" color="-11574/-10271420" readonly-code="true" readonly-data="true" />
<environment-type id="other" name="Other" description="" color="-1576/-10724543" readonly-code="false" readonly-data="false" />
</environment-types>
<visibility-settings>
<connection-tabs value="true" />
<dialog-headers value="true" />
<object-editor-tabs value="true" />
<script-editor-tabs value="false" />
<execution-result-tabs value="true" />
</visibility-settings>
</environment>
</general-settings>
</component>
</project>

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11" project-jdk-type="Python SDK" />
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/实验.iml" filepath="$PROJECT_DIR$/.idea/实验.iml" />
</modules>
</component>
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -0,0 +1,47 @@
import tkinter as tk
import subprocess
import threading
# 使用线程来运行 NEW.py和 NEV.py。
def run_new():
try:
threading.Thread(target=lambda: subprocess.run(["python", "NEW.py"])).start()
except FileNotFoundError:
print("找不到NEW.py文件")
def run_nev():
try:
threading.Thread(target=lambda: subprocess.run(["python", "NEV.py"])).start()
except FileNotFoundError:
print("找不到NEV.py文件")
# 创建主窗口
root = tk.Tk()
root.title("文件安全传输工具")
# 设置窗口大小
root.geometry("300x150")
# 创建标签
label = tk.Label(root, text="请选择您的身份:")
label.pack(pady=10)
# 创建按钮框架,用于在同一行放置按钮
button_frame = tk.Frame(root)
button_frame.pack()
# 创建发送方按钮
sender_button = tk.Button(button_frame, text="发送方", command=run_new)
sender_button.pack(side=tk.LEFT, padx=10)
# 创建接收方按钮
receiver_button = tk.Button(button_frame, text="接收方", command=run_nev)
receiver_button.pack(side=tk.LEFT, padx=10)
# 创建关闭按钮
confirm_button = tk.Button(button_frame, text="关闭", command=root.destroy)
confirm_button.pack(side=tk.LEFT, padx=10)
# 运行主循环
root.mainloop()

195
NEV.py

@ -0,0 +1,195 @@
import os
import pickle
import socket
import tkinter as tk
from tkinter import filedialog, ttk, messagebox
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
import hashlib
# 去除填充函数
def unpad(data):
padding_length = data[-1]
if padding_length > len(data):
return data
return data[:-padding_length]
# 解密文件函数
def decrypt_file(encrypted_data, key, iv, algorithm, mode):
mode_mapping = {
"CBC": modes.CBC,
"CFB": modes.CFB
}
if algorithm == "AES":
# 对于AES算法IV长度为16字节无需处理
cipher = Cipher(algorithms.AES(key), mode_mapping[mode](iv))
elif algorithm == "DES":
# 确保IV长度为8字节
iv = iv[:8]
cipher = Cipher(algorithms.TripleDES(key), mode_mapping[mode](iv))
else:
raise ValueError("不支持该算法")
decryptor = cipher.decryptor()
decrypted_data = decryptor.update(encrypted_data) + decryptor.finalize()
return decrypted_data
# 计算哈希值函数
def calculate_hash(data):
digest = hashes.Hash(hashes.SHA256())
digest.update(data)
return digest.finalize()
# 验证签名函数
def verify_signature(public_key, signature, hash_value):
try:
public_key.verify(
signature,
hash_value,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
return True
except Exception:
return False
# 解密对称密钥函数
def decrypt_symmetric_key(private_key, encrypted_key):
decrypted_key = private_key.decrypt(
encrypted_key,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
return decrypted_key
# 计算文件的 MD5 校验和
def calculate_md5(data):
md5 = hashlib.md5()
md5.update(data)
return md5.hexdigest()
# 接收文件函数
def receive_file(server_ip, server_port, output_dir, algorithm, mode):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((server_ip, server_port))
s.listen(1)
print(f"等待连接,监听端口 {server_port}...")
conn, addr = s.accept()
with conn:
print(f"接收到连接来自: {addr}")
data = b""
while True:
packet = conn.recv(4096)
if not packet:
break
data += packet
package = pickle.loads(data)
encrypted_file = package['encrypted_file']
iv = package['iv']
encrypted_symmetric_key = package['encrypted_symmetric_key']
signature = package['signature']
received_algorithm = package['algorithm']
received_mode = package['mode']
received_md5_checksum = package['md5_checksum']
file_extension = package['file_extension']
# 从封装包中提取发送方公钥
sender_public_pem = package['sender_public_key']
sender_public_key = serialization.load_pem_public_key(sender_public_pem)
if algorithm!= received_algorithm or mode!= received_mode:
raise ValueError("选择的解密算法或模式与发送方不一致")
with open("receiver_private_key.pem", "rb") as f:
receiver_private_key = serialization.load_pem_private_key(
f.read(),
password=None
)
symmetric_key = decrypt_symmetric_key(receiver_private_key, encrypted_symmetric_key)
decrypted_file = decrypt_file(encrypted_file, symmetric_key, iv, algorithm, mode)
decrypted_file = unpad(decrypted_file)
file_hash = calculate_hash(encrypted_file)
is_valid = verify_signature(sender_public_key, signature, file_hash)
return is_valid, output_dir, file_extension, decrypted_file
# 主函数,用于启动 GUI 界面
def receiver_main():
def select_output_dir():
output_dir.set(filedialog.askdirectory())
def start_receiving():
if not output_dir.get():
print("请选择保存文件的路径!")
return
algorithm = algorithm_var.get()
mode = mode_var.get()
try:
is_valid, output_dir_path, file_extension, decrypted_file = receive_file(
server_ip.get(), int(server_port.get()), output_dir.get(), algorithm, mode
)
result_label.config(text=f"接收方验证签名结果: {is_valid}")
if is_valid:
output_file_path = os.path.join(output_dir_path, f"decrypted_file.{file_extension}")
with open(output_file_path, "wb") as f:
f.write(decrypted_file)
messagebox.showinfo("提示", "接收成功")
except Exception as e:
print(f"接收过程中发生错误: {e}")
root = tk.Tk()
root.title("接收方")
root.geometry("450x300") # 适当增加窗口高度以显示新标签
server_ip = tk.StringVar(value="127.0.0.1")
server_port = tk.StringVar(value="12345")
output_dir = tk.StringVar()
algorithm_var = tk.StringVar(value="AES")
mode_var = tk.StringVar(value="CBC")
ttk.Label(root, text="监听 IP").grid(row=0, column=0, sticky=tk.W, pady=5)
ttk.Entry(root, textvariable=server_ip).grid(row=0, column=1, pady=5)
ttk.Label(root, text="监听端口:").grid(row=1, column=0, sticky=tk.W, pady=5)
ttk.Entry(root, textvariable=server_port).grid(row=1, column=1, pady=5)
ttk.Label(root, text="选择保存文件的路径:").grid(row=2, column=0, sticky=tk.W, pady=5)
ttk.Entry(root, textvariable=output_dir, width=30).grid(row=2, column=1, pady=5)
ttk.Button(root, text="选择目录", command=select_output_dir).grid(row=2, column=2, pady=5)
ttk.Label(root, text="选择解密算法:").grid(row=3, column=0, sticky=tk.W, pady=5)
ttk.Combobox(root, textvariable=algorithm_var, values=["AES", "DES"], state="readonly").grid(row=3, column=1, pady=5)
ttk.Label(root, text="选择解密模式:").grid(row=4, column=0, sticky=tk.W, pady=5)
ttk.Combobox(root, textvariable=mode_var, values=["CBC", "CFB"], state="readonly").grid(row=4, column=1, pady=5)
ttk.Button(root, text="开始接收文件", command=start_receiving).grid(row=5, columnspan=3, pady=20)
# 新增显示验证结果的标签
result_label = ttk.Label(root, text="")
result_label.grid(row=6, columnspan=3, pady=10)
root.mainloop()
if __name__ == "__main__":
receiver_main()

269
NEW.py

@ -0,0 +1,269 @@
import os
import pickle
import socket
import tkinter as tk
from tkinter import filedialog, ttk, messagebox
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
import hashlib
# 生成并保存发送方密钥对
def generate_and_save_sender_keys():
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
)
public_key = private_key.public_key()
with open('sender_private_key.pem', 'wb') as f:
f.write(private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
))
with open('sender_public_key.pem', 'wb') as f:
f.write(public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
))
return private_key, public_key
# 加载发送方密钥对
def load_sender_keys():
try:
with open('sender_private_key.pem', 'rb') as f:
private_key = serialization.load_pem_private_key(
f.read(),
password=None
)
with open('sender_public_key.pem', 'rb') as f:
public_key = serialization.load_pem_public_key(f.read())
return private_key, public_key
except FileNotFoundError:
return generate_and_save_sender_keys()
sender_private_key, sender_public_key = load_sender_keys()
# 用于存储接收方公钥的变量
receiver_public_key = None
# 填充数据函数
def pad(data, block_size):
padding_length = block_size - (len(data) % block_size)
if padding_length == 0:
padding_length = block_size
padding = bytes([padding_length]) * padding_length
return data + padding
# 加密文件函数
def encrypt_file(file_path, key, algorithm, mode):
with open(file_path, 'rb') as f:
file_data = f.read()
if algorithm == "AES":
block_size = 16
elif algorithm == "DES":
block_size = 8
else:
raise ValueError("Unsupported algorithm")
file_data = pad(file_data, block_size)
mode_mapping = {
"CBC": modes.CBC,
"CFB": modes.CFB
}
if algorithm == "AES":
iv = os.urandom(16)
elif algorithm == "DES":
iv = os.urandom(8) # 生成8字节的IV用于DES算法
else:
raise ValueError("Unsupported algorithm")
if algorithm == "AES":
cipher = Cipher(algorithms.AES(key), mode_mapping[mode](iv))
elif algorithm == "DES":
cipher = Cipher(algorithms.TripleDES(key), mode_mapping[mode](iv))
else:
raise ValueError("Unsupported algorithm")
encryptor = cipher.encryptor()
encrypted_data = encryptor.update(file_data) + encryptor.finalize()
return encrypted_data, iv
# 计算哈希值函数
def calculate_hash(data):
digest = hashes.Hash(hashes.SHA256())
digest.update(data)
return digest.finalize()
# 对哈希值进行签名函数
def sign_hash(private_key, hash_value):
signature = private_key.sign(
hash_value,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
return signature
# 加密对称密钥函数
def encrypt_symmetric_key(public_key, symmetric_key):
encrypted_key = public_key.encrypt(
symmetric_key,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
return encrypted_key
# 计算文件的 MD5 校验和
def calculate_md5(data):
md5 = hashlib.md5()
md5.update(data)
return md5.hexdigest()
# 发送文件函数
def send_file(server_ip, server_port, package):
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((server_ip, server_port))
s.sendall(pickle.dumps(package))
return True
except Exception as e:
print(f"连接失败: {e}")
return False
# 导入接收方公钥的函数
def import_receiver_public_key():
global receiver_public_key
file_path = filedialog.askopenfilename(filetypes=[("PEM files", "*.pem")])
if file_path:
try:
with open(file_path, 'rb') as f:
receiver_public_key = serialization.load_pem_public_key(f.read())
messagebox.showinfo("提示", "接收方公钥导入成功")
except Exception as e:
messagebox.showerror("错误", f"导入接收方公钥失败: {e}")
# 主函数,用于启动 GUI 界面
def sender_main():
def select_file():
file_path.set(filedialog.askopenfilename())
def send():
global receiver_public_key
file = file_path.get()
algorithm = algorithm_var.get()
mode = mode_var.get()
if not file:
messagebox.showerror("错误", "请选择文件")
return
if algorithm == "AES":
key_size = 32
elif algorithm == "DES":
key_size = 24
else:
print("不支持的算法!")
return
if mode == "CBC":
pass
elif mode == "CFB":
pass
else:
print("不支持的模式!")
return
if not receiver_public_key:
messagebox.showerror("错误", "请导入证书")
return
symmetric_key = os.urandom(key_size)
encrypted_file, iv = encrypt_file(file, symmetric_key, algorithm, mode)
file_hash = calculate_hash(encrypted_file)
signature = sign_hash(sender_private_key, file_hash)
sender_public_pem = sender_public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
encrypted_symmetric_key = encrypt_symmetric_key(receiver_public_key, symmetric_key)
md5_checksum = calculate_md5(encrypted_file)
file_extension = os.path.splitext(file)[1][1:]
# 在封装包中添加发送方公钥
package = {
'encrypted_file': encrypted_file,
'iv': iv,
'encrypted_symmetric_key': encrypted_symmetric_key,
'signature': signature,
'algorithm': algorithm,
'mode': mode,
'md5_checksum': md5_checksum,
'file_extension': file_extension,
'sender_public_key': sender_public_pem
}
if send_file(server_ip.get(), int(server_port.get()), package):
messagebox.showinfo("提示", "发送成功")
else:
messagebox.showerror("错误", "连接失败")
root = tk.Tk()
root.title("发送方")
root.geometry("490x250")
file_path = tk.StringVar()
algorithm_var = tk.StringVar(value="AES")
mode_var = tk.StringVar(value="CBC")
server_ip = tk.StringVar(value="127.0.0.1")
server_port = tk.StringVar(value="12345")
ttk.Label(root, text="选择文件:").grid(row=0, column=0, sticky=tk.W, pady=5)
ttk.Entry(root, textvariable=file_path, width=30).grid(row=0, column=1, pady=5)
ttk.Button(root, text="浏览", command=select_file).grid(row=0, column=2, pady=5)
ttk.Button(root, text="导入证书", command=import_receiver_public_key).grid(row=0, column=3, pady=5)
ttk.Label(root, text="选择加密算法:").grid(row=1, column=0, sticky=tk.W, pady=5)
ttk.Combobox(root, textvariable=algorithm_var, values=["AES", "DES"], state="readonly").grid(row=1, column=1, pady=5)
ttk.Label(root, text="选择加密模式:").grid(row=2, column=0, sticky=tk.W, pady=5)
ttk.Combobox(root, textvariable=mode_var, values=["CBC", "CFB"], state="readonly").grid(row=2, column=1, pady=5)
ttk.Label(root, text="接收方 IP").grid(row=3, column=0, sticky=tk.W, pady=5)
ttk.Entry(root, textvariable=server_ip).grid(row=3, column=1, pady=5)
ttk.Label(root, text="接收方端口:").grid(row=4, column=0, sticky=tk.W, pady=5)
ttk.Entry(root, textvariable=server_port).grid(row=4, column=1, pady=5)
ttk.Button(root, text="发送文件", command=send).grid(row=5, columnspan=3, pady=20)
root.mainloop()
if __name__ == "__main__":
sender_main()

Binary file not shown.

Binary file not shown.

@ -0,0 +1,77 @@
import socket
import json
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import serialization, hashes
def generate_key():
return Fernet.generate_key()
def encrypt_file(file_path, key):
with open(file_path, 'rb') as file:
data = file.read()
fernet = Fernet(key)
encrypted_data = fernet.encrypt(data)
return encrypted_data
def encrypt_key(public_key, symmetric_key):
encrypted_key = public_key.encrypt(
symmetric_key,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
return encrypted_key
def main():
host = '127.0.0.1'
port = 49670
# 创建rsa密钥对
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
public_key = private_key.public_key()
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((host, port))
server_socket.listen(1)
print("Server is listening...")
conn, addr = server_socket.accept()
print(f"Connection from {addr}")
# 发送公钥
pem = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
conn.sendall(pem)
# 加密文件,这里假设要发送的文件名为 'example.txt',可根据实际情况修改
file_path = 'example.txt'
symmetric_key = generate_key()
encrypted_data = encrypt_file(file_path, symmetric_key)
# 用公钥加密对称密钥
encrypted_key = encrypt_key(public_key, symmetric_key)
# 构建数字信封确保数据编码使用更通用的utf-8格式
envelope = {
'algorithm': 'AES',
'key': encrypted_key.hex(),
'file_data': encrypted_data.decode('utf-8')
}
# 发送数字信封先转换为JSON字符串再编码为字节类型发送
conn.sendall(json.dumps(envelope).encode('utf-8'))
conn.close()
print("File sent successfully.")
if __name__ == "__main__":
main()

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCFkCLhWcpNPbTu
12H30PAvVJY7ui5BauTEzfILeH0ki9x3HeUvGmFxeY6JVCO+obio8NT1DWaVl2NC
6SRhnLRGg2Oq4LgbAOBqBpatF7GL3e1aHzugWmCQdH3oFgw2bQQOrK7OoZc0FXSq
DvfvMkxn4cgVv75Rcz/GaUzGnmNCzjBH+sQrnQj9my694YUT+HSnabXHDje+EZ2I
j7wbjQl941RV0mITt4bgJdVE09UuVEIz76K/yRMzrvwsSUwokvt9XFsQvRGyGUC9
42BPlvxVGz744P6DuXIZ3Dt+DGNhNJliIuLNhIolGO85eqtbPHKeMDPvx1pO+Y4B
us9AplA/AgMBAAECggEAJoUUWjPAMZirVvrNKWCb9LqLfXxLnNhMVColNYOxa9ne
Yog/sd8E3Wo2XoriqDcR/789W9Nak6gOm5yLvo8oOvHny791uWv+TPXLfO5JaVI/
Au/hDXUjRmYibc32BbhZJDZPUA6wgffyJp2cieLSwF8Qip07MVhwuzNhTiMd84UD
H8vdDCPi6wZ41glMzGCJVRJAAmxz8XkYeMz6ghtMtilAxz30IBnKAFsSgFQGtZJk
Hg2STxvMWMkn3j6Vnl88YfMAhe+fAbqhDuh/Uy0Py+XaTULUNOJXZtKyCwO3leJm
PdfeCoQVG4/BYZhd7cZgT9pv0d0FTl9vWg/FC88h4QKBgQC8iiF5B/8/CRiVbq17
c31ka7pb2oBSJlDpemN7vhA6D9ZwFDDvsFi/ezHLUuizZvuo9pYsFkNKWtgZKE4w
/nCZqP4HTC9rRIIFf7/XlJuMrRXuAkkbyRWSP9DxfudO+QBVqdXp2pJoPJfiFrkb
mM3t3GjL7eTCdo9ixItOOsx8jwKBgQC1WkIPegQdbfhCe9taH/DxaWcJkgSpVdwC
Yhm7dEj+DngRcmTDehXJmaA6mqVMGK2Q4HeYNzUmQPzpAp7NyW4m7E87hj9uzA2m
2DXzfZuf3GM6vE+DKif3umBV0yEW7oJb6BxE1RDGUC/vfwXinxBDTtiEYOZ26fi5
1vqcugApUQKBgQClOoCfKuz79yK+QqJyYAHx8Z7+RHzUgZPDKWjp1uUtnReWXXuN
cwQzuukmgOBB6Ox/ZKqytEgAb6CWW4Y61aEkaL9G8fNUlFNGMnCToz62iDGBxir/
2Le41YhtO4PG59ztNcusB8rq4r9Qeg17K+y8mb6ViURDT9fU/N4AjvMJ7QKBgGey
foee+29gjE5nyBuWnA1Oec5tIiE5qR3rvk8DxSEQYPOI97kWvBKUt5wLBW2nxsdK
stfk6Y1AJ92M1AVTopq7EOs2blsKbtvyUZczQaN9P3g8aTLVDhmHBsLMgOU96Ghp
JpDtTDQ5cc9+UH0u+vuhwAih5+YjD0gkdxTa/nChAoGBAJJ7Ps+GGlnbAouFMT1S
bwRuNAVZcNzu5ud0jKAPEvNwa9WFlFObh77taI9aIqGzcibena+7+6ld7sBzo769
umYbe+3o4nqDIzhL0rZuSG8cq6ajkq1al9WVG/nlJ99YBjaEltmBVVOQ3ysBuGZj
HR7g/XAyJzUFadT8BEdh/vZm
-----END PRIVATE KEY-----

@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhZAi4VnKTT207tdh99Dw
L1SWO7ouQWrkxM3yC3h9JIvcdx3lLxphcXmOiVQjvqG4qPDU9Q1mlZdjQukkYZy0
RoNjquC4GwDgagaWrRexi93tWh87oFpgkHR96BYMNm0EDqyuzqGXNBV0qg737zJM
Z+HIFb++UXM/xmlMxp5jQs4wR/rEK50I/ZsuveGFE/h0p2m1xw43vhGdiI+8G40J
feNUVdJiE7eG4CXVRNPVLlRCM++iv8kTM678LElMKJL7fVxbEL0RshlAveNgT5b8
VRs++OD+g7lyGdw7fgxjYTSZYiLizYSKJRjvOXqrWzxynjAz78daTvmOAbrPQKZQ
PwIDAQAB
-----END PUBLIC KEY-----

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC37VWLRKKVTRnY
OMJuebhBoaX30zUhv9KiVpCJ1RY+OT3s+4vU2OjaJt6ql6E1xPPbecKGPc+9aZFj
18jZsZgXC4aVpANP17ApzniAXXjoyYsrAL0e1dxGviZolDfrDJTllP2FIyfmFgRn
GUVrfcUqSL5DJ/GU9qR1EhSHBVUwmet6HFAXwRDJYZ49YvRHeExnzv7p4qgQkEy1
G9/phYRS26tvI+910eRRbWcKuGounr1ZOB81Aym8RnRlipUipqpTiCUWvvY2TpEe
jSPA5WCjzjom8Jo8zepqvImB7G2zIy9/0C+daLtJZUvoCy8CHFmqk2buQXWUIu4C
6mrsY76fAgMBAAECggEAAI1BEIvTxitiKJ2qQKu2lNBm7bG4iBctVQSb4qyGNkyl
5DG1QkFJXjgNbaR3ZlllKF6fcwsU/op3/L1Ao+kaZEM16JQKNZBbYVD34teQ5Yog
FvRmhbY5wA+8qSuk2rLpLLgh89krsAUVywHL7/tYUJDvy3M9MlB3eAqojH4D0G3Z
llKhYThTmtjIWvvSAXCLL0QSXP/DOGgU4OPLsJ0vxrvXObkzT7WHeHLbfB3y9kTj
An3zEaTmQulEbpq4QOKjIETtyLcWTbUxaL5baikGWRAkS+BrncSfNqpgsnvgyg1f
nuTdi2TC+VZIDal+HtYGQgwtIrHzu53NgXUZE3D21QKBgQDhFmtpQoK8LfOkLPW6
6el9VjvRqvyrLo+ymHqxpYUxPXKFwToqa3TeKY/56kx5cy9oogCV8LwR0Yt7awiz
Syxv8RBZoPsaVuEaY3FunVcPC+eCE1O2N0pOqIy1Ff/6G94y37U7sSm5oCHJTRET
ApHJt8m1LmFRRS5QYnzn3Js1/QKBgQDRL82O6u4Ei+11ZjyzQgA75iukZVWKNHrI
haDTbwdasaItlLKO+xJQEN0IzkPNbuEyrqRMWtqyWaT2fpCkJXZWom8IzLmhL3SD
Htdiq2VvCt/Pq6SELNzLJT7pbVzuA7HosOK+z+Zc5+TOEPORgKydlNVY452iJP/Y
lGLHAEtbywKBgGpMUjGFjYQdF2DDMtEwwmnEnb9oxqZ4+LfZNqhKiNo2MK1mEXgT
A0Af1LSrp637bbo2N5yX8dlgYkTIyXUS3UuIRrZtReiseuYhbGJWv9SFRLGzOudk
uRzokHq8hwSwwIC6ETa9df0J2KreUF/v6LWgrAt6ec8Nos+nk2FUV6BpAoGBAILY
VMp9do4PfGN/pJ43vW+6JDg7TksZUmfU9ejqvP3kuF2schfvQeAk/C0C3/RC08fg
51H/TmZank20kwKpkCDWj39AlygUR9uwUecc8GCJu77pTQmECkNjM7vMtWEHnKPA
6MOTxTL9teeTQNcVVmNm8iAcl8ARRpsRDcwOChULAoGBALiGuaQvG0uUPjt3Za+n
I0xV5B5dymFtxjgfHZwldnrW+9rF5omGswLDhn7Iya9+UIoX1rGdG+qqWMtIJcmz
g2cz2hRdX67tdxnanlMb6ALrQdAXEhLLnXMJAsRxeqsEpUYf+OypYm6XkJkDmgCz
PfyGudk3oG0VCrXP21/P9H/A
-----END PRIVATE KEY-----

@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt+1Vi0SilU0Z2DjCbnm4
QaGl99M1Ib/SolaQidUWPjk97PuL1Njo2ibeqpehNcTz23nChj3PvWmRY9fI2bGY
FwuGlaQDT9ewKc54gF146MmLKwC9HtXcRr4maJQ36wyU5ZT9hSMn5hYEZxlFa33F
Kki+QyfxlPakdRIUhwVVMJnrehxQF8EQyWGePWL0R3hMZ87+6eKoEJBMtRvf6YWE
UturbyPvddHkUW1nCrhqLp69WTgfNQMpvEZ0ZYqVIqaqU4glFr72Nk6RHo0jwOVg
o846JvCaPM3qaryJgextsyMvf9AvnWi7SWVL6AsvAhxZqpNm7kF1lCLuAupq7GO+
nwIDAQAB
-----END PUBLIC KEY-----

@ -0,0 +1,25 @@
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
def generate_receiver_keys():
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
)
public_key = private_key.public_key()
# 保存私钥到文件
with open('receiver_private_key.pem', 'wb') as f:
f.write(private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
))
# 保存公钥到文件
with open('receiver_public_key.pem', 'wb') as f:
f.write(public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
))
generate_receiver_keys()
Loading…
Cancel
Save