You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于RSA的Python加密框架解密.docx文件时出现字体异常

问题分析与修复:RSA加密DOCX文件后解密显示异常

核心问题根源

  1. 密钥不匹配:原代码加密时随机生成公钥的e值,解密时重新生成密钥对,导致加密和解密使用的密钥不一致,直接造成解密数据错误。
  2. 二进制文件被当作文本处理:DOCX是二进制压缩格式,原代码用文本编码(utf-8/latin-1)读取文件,将二进制字节转成字符串后再加密,解密后又转成utf-8字节写入,完全破坏了原始文件的二进制结构。
  3. 加密逻辑适配错误:原encrypt/decrypt函数基于字符的ord()值处理,仅适用于纯文本,无法正确处理二进制字节数据。

修复方案

1. 固定密钥对

由于使用固定的p=61和q=53,可以直接固定公钥e和私钥d,确保加密解密使用同一组密钥:

  • n = 61*53 = 3233
  • phi = (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混合方案:

  1. 用AES加密大文件
  2. 用RSA加密AES的密钥
  3. 解密时先用RSA解密AES密钥,再用AES解密文件

内容的提问来源于stack exchange,提问作者Nguyễn Võ Khánh Văn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 21:30:57