基于RSA的Python加密框架解密.docx文件时出现字体异常
问题分析与修复:RSA加密DOCX文件后解密显示异常
核心问题根源
- 密钥不匹配:原代码加密时随机生成公钥的
e值,解密时重新生成密钥对,导致加密和解密使用的密钥不一致,直接造成解密数据错误。 - 二进制文件被当作文本处理:DOCX是二进制压缩格式,原代码用文本编码(utf-8/latin-1)读取文件,将二进制字节转成字符串后再加密,解密后又转成utf-8字节写入,完全破坏了原始文件的二进制结构。
- 加密逻辑适配错误:原
encrypt/decrypt函数基于字符的ord()值处理,仅适用于纯文本,无法正确处理二进制字节数据。
修复方案
1. 固定密钥对
由于使用固定的p=61和q=53,可以直接固定公钥e和私钥d,确保加密解密使用同一组密钥:
n = 61*53 = 3233phi = (61-1)*(53-1) = 3120- 选择与
phi互质的e=17,对应的d=2753(通过模逆运算得出)
2. 改用二进制方式处理文件
直接读写文件的原始字节,避免任何编码转换对二进制数据的破坏。
3. 调整加密解密函数
修改函数以处理字节数组,而非字符串字符。
修改后的完整代码
import random import tkinter as tk from tkinter import filedialog def gcd(a, b): while b != 0: a, b = b, a % b return a def mod_inverse(a, m): if gcd(a, m) != 1: return None u1, u2, u3 = 1, 0, a v1, v2, v3 = 0, 1, m while v3 != 0: q = u3 // v3 v1, v2, v3, u1, u2, u3 = u1 - q * v1, u2 - q * v2, u3 - q * v3, v1, v2, v3 return u1 % m # 处理字节的加密函数 def encrypt_bytes(data_bytes, public_key): e, n = public_key cipher = [pow(byte, e, n) for byte in data_bytes] return cipher # 处理字节的解密函数 def decrypt_bytes(cipher, private_key): d, n = private_key data_bytes = bytes([pow(num, d, n) for num in cipher]) return data_bytes def browse_file(): filepath = filedialog.askopenfilename() file_entry.delete(0, tk.END) file_entry.insert(tk.END, filepath) def encrypt_file(): # 使用固定密钥对,确保加密解密一致 p = 61 q = 53 n = p * q e = 17 public_key = (e, n) filepath = file_entry.get() # 二进制读取原始文件 with open(filepath, "rb") as f: data_bytes = f.read() encrypted_data = encrypt_bytes(data_bytes, public_key) encrypted_filepath = filepath + ".encrypted" # 将加密后的整数列表保存为文本格式 with open(encrypted_filepath, "w", encoding="utf-8") as f: f.write(' '.join(map(str, encrypted_data))) result_label.config(text="File encrypted successfully.") def decrypt_file(): # 使用与加密完全一致的密钥对 p = 61 q = 53 n = p * q d = 2753 private_key = (d, n) filepath = file_entry.get() try: with open(filepath, "r", encoding="utf-8") as f: encrypted_data = f.read().split() except UnicodeDecodeError: result_label.config(text="Failed to open encrypted file: Invalid encoding (UTF-8)") return try: encrypted_data = list(map(int, encrypted_data)) except ValueError: result_label.config(text="Invalid encrypted data format") return decrypted_data_bytes = decrypt_bytes(encrypted_data, private_key) # 生成解密后的文件路径 decrypted_filepath = filepath[:-10] + ".decrypted" try: with open(decrypted_filepath, "wb") as f: f.write(decrypted_data_bytes) except Exception as e: result_label.config(text="Failed to write decrypted file: " + str(e)) return result_label.config(text="File decrypted successfully.") # 初始化GUI部分 window = tk.Tk() window.title("RSA File Encryptor") window.geometry("500x350") window.configure(bg='#99CCFF') file_entry = tk.Entry(window, width=40) file_entry.place(x=20, y=120) browse_button = tk.Button(window, text="Browse", command=browse_file) browse_button.place(x=290, y=120) encrypt_button = tk.Button(window, text="Encrypt", command=encrypt_file) encrypt_button.place(x=290, y=170) decrypt_button = tk.Button(window, text="Decrypt", command=decrypt_file) decrypt_button.place(x=290,y=220) result_label = tk.Label(window, bg='#99CCFF') result_label.place(x=240, y= 270) window.mainloop()
额外说明
RSA算法本身设计用于加密小数据(如对称密钥、哈希值),加密大文件(如DOCX)效率极低。实际生产环境中,建议采用对称加密+RSA混合方案:
- 用AES加密大文件
- 用RSA加密AES的密钥
- 解密时先用RSA解密AES密钥,再用AES解密文件
内容的提问来源于stack exchange,提问作者Nguyễn Võ Khánh Văn
相关产品推荐
相关产品推荐

