提问人:Nguyễn Võ Khánh Vân 提问时间:10/25/2023 最后编辑:XMehdi01Nguyễn Võ Khánh Vân 更新时间:10/26/2023 访问量:66
尝试解密加密的 .docx 文件时出现字体错误
Font error when trying to decrypt an encrypted .docx file
问:
我正在做一个项目,该项目创建了一个框架,用于保护使用 RSA 用 Python 编写的用户登录信息。当我尝试运行框架时,一切都很正常,直到进入解密阶段。在显示字母字体选项的框中。预览文本的字体似乎有错误。在此处输入图像描述 在此处输入图像描述
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 generate_keypair(p, q):
n = p * q
phi = (p - 1) * (q - 1)
e = random.randrange(1, phi)
g = gcd(e, phi)
while g != 1:
e = random.randrange(1, phi)
g = gcd(e, phi)
d = mod_inverse(e, phi)
return (e, n), (d, n)
def encrypt(message, public_key):
e, n = public_key
cipher = [pow(ord(char), e, n) for char in message]
return cipher
def decrypt(cipher, private_key):
d, n = private_key
message = [chr(pow(char, d, n)) for char in cipher]
return ''.join(message)
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
public_key, _ = generate_keypair(p, q)
filepath = file_entry.get()
try:
with open(filepath, "r", encoding="utf-8") as f:
plaintext = f.read()
except UnicodeDecodeError:
with open(filepath, "r", encoding="latin-1") as f: # Sử dụng mã hóa "latin-1" nếu gặp lỗi UnicodeDecodeError
plaintext = f.read()
encrypted_data = encrypt(plaintext, 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
_, private_key = generate_keypair(p, q)
filepath = file_entry.get()
try:
with open(filepath, "r", encoding="utf-8") as f: # Sử dụng mã hóa utf-8
encrypted_data = f.read().split()
except UnicodeDecodeError:
result_label.config(text="Failed to open decrypted file: Invalid encoding (UTF-8)")
return
encrypted_data = list(map(int, encrypted_data))
decrypted_data = decrypt(encrypted_data, private_key)
# Create a decrypted file with a ".decrypted" extension
decrypted_filepath = filepath[:-10] # Remove ".encrypted" from the end of the file name
decrypted_filepath += ".decrypted"
# Convert decrypted data to bytes before writing (using utf-8 encoding)
decrypted_data_bytes = bytes(decrypted_data, 'utf-8')
try:
with open(decrypted_filepath, "wb") as f:
f.write(decrypted_data_bytes)
except Exception as e:
result_label.config(text="Failed to open decrypted file: " + str(e))
return
result_label.config(text="File decrypted successfully.")
# Open the decrypted file
try:
with open(decrypted_filepath, "rb") as f:
decrypted_data_bytes = f.read()
# Now you can work with the decrypted_data_bytes as needed
except Exception as e:
result_label.config(text="Failed to open decrypted file: " + str(e))
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)
简要介绍如何使用此框架:
- 点击“浏览”
- 进入文本栏并选择一个 XYZ.docx 文件
- 点击“加密”(应显示“文件加密成功”
- 再次点击“浏览”
- 在所选的 .docx 文件下方将有另一个 XYZ.docx.encrypted 文件,请选择它
- 选择文件后,点击“解密”
- 在所选的 .docx 文件下方将有另一个 XYZ.docx.decrypted 文件,请打开它
我希望找到潜在的错误并解决这个问题,以便解密后文本可以正常
答:
0赞
Tấn Nguyên
10/25/2023
#1
我认为您对 RSA 用例有误解,这不是文件加密的典型用途。文件越大,加密文件就越大。在这个“学习案例”中,我可以向您展示并纠正您的 RSA 实施的简单基础:
- 您正在尝试获取 ,但加密应该使用字节。尝试编码也是不合理的。
uft-8
latin-1
- 您不能在解密过程中生成私钥,私钥应在加密时生成并保存在不同的位置,以便在解密中重复使用
- 加密过程需要按顺序进行:获取文件的字节 - >加密以加密整数 - >将整数转换为字节 - >保存加密字节并保存私钥
- 解密过程需要按顺序进行:获取加密的字节和私钥 -> 转换为密码整数 ->解密密码整数为字节 -> concat 字节。
import random
PREVIEW_LENGTH = 15
BYTES_PADDING_SIZE = 2
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 generate_keypair(p, q):
n = p * q
phi = (p - 1) * (q - 1)
e = random.randrange(1, phi)
g = gcd(e, phi)
while g != 1:
e = random.randrange(1, phi)
g = gcd(e, phi)
d = mod_inverse(e, phi)
return (e, n), (d, n)
def encrypt(bytes, public_key):
e, n = public_key
print('Encrypting with public key', public_key)
print('Origin bytes', bytes[:PREVIEW_LENGTH])
# Encrypt each byte to an integer m^e mod n
cipher_integers = [pow(byte, e, n) for byte in bytes]
print('Cipher integers', cipher_integers[:PREVIEW_LENGTH])
# Convert integers to bytes and concatenate them
cipher_bytes = b''.join(int_to_bytes(char) for char in cipher_integers)
print('Cipher bytes',cipher_bytes[:PREVIEW_LENGTH])
return cipher_bytes
def decrypt(cipher_bytes, private_key):
d, n = private_key
print('Decrypting with private key', private_key)
print('Cipher bytes', cipher_bytes[:PREVIEW_LENGTH])
cipher_integers = [bytes_to_int(cipher_bytes[i:i + BYTES_PADDING_SIZE]) for i in range(0, len(cipher_bytes), BYTES_PADDING_SIZE)]
print('Cipher integers', cipher_integers[:PREVIEW_LENGTH])
decrypted_bytes = [pow(cipher_int, d, n) for cipher_int in cipher_integers]
decrypted_bytes = bytes(decrypted_bytes)
print('Origin bytes', decrypted_bytes[:PREVIEW_LENGTH])
return decrypted_bytes
def int_to_bytes(n, padding=BYTES_PADDING_SIZE):
# Convert an integer to its byte representation
return n.to_bytes(padding, byteorder='big')
def bytes_to_int(b):
# Convert bytes to integer
return int.from_bytes(b, byteorder='big')
def key_to_pem(e, n, d):
# Construct the PEM strings for public and private keys
public_key_pem = f"-----BEGIN RSA PUBLIC KEY-----\n{int_to_bytes(e).hex()}\n{int_to_bytes(n).hex()}\n-----END RSA PUBLIC KEY-----\n"
private_key_pem = f"-----BEGIN RSA PRIVATE KEY-----\n{int_to_bytes(n).hex()}\n{int_to_bytes(d).hex()}\n-----END RSA PRIVATE KEY-----\n"
return public_key_pem, private_key_pem
def pem_to_key(private_key_pem):
# Remove PEM header and footer
private_key_pem = private_key_pem.replace("-----BEGIN RSA PRIVATE KEY-----", "").replace("-----END RSA PRIVATE KEY-----", "").strip()
# Convert hex strings to integers
n_hex, d_hex = private_key_pem.split('\n')
n = bytes_to_int(bytes.fromhex(n_hex))
d = bytes_to_int(bytes.fromhex(d_hex))
return d, n
def encrypt_file(filepath):
p = 61
q = 53
public_key, private_key = generate_keypair(p, q)
with open(filepath, "rb") as f:
bytes = f.read()
encrypted_data = encrypt(bytes, public_key)
encrypted_filepath = filepath + ".encrypted"
with open(encrypted_filepath, "wb") as f:
f.write(encrypted_data)
print("File encrypted successfully.")
_, private_key_pem = key_to_pem(public_key[0], public_key[1], private_key[0])
return encrypted_filepath, private_key_pem
def decrypt_file(filepath, private_key_pem):
private_key = pem_to_key(private_key_pem)
with open(filepath, "rb") as f:
encrypted_data = f.read()
decrypted_data = decrypt(encrypted_data, private_key)
# Create a decrypted file with a ".decrypted" extension
decrypted_filepath = filepath.replace('.encrypted', '') # Remove ".encrypted" from the end of the file name
decrypted_filepath = 'decrypted_' + decrypted_filepath
with open(decrypted_filepath, "wb") as f:
f.write(decrypted_data)
print("File decrypted successfully.")
return decrypted_filepath
def main():
sample_path = 'file-sample_1MB.docx'
# Download sample for testing purpose, comment this if you already have a file
# import requests
# url = "https://file-examples.com/storage/fe805ba0cc65378da968c5c/2017/02/file-sample_1MB.docx"
# response = requests.get(url)
# if response.status_code != 200:
# raise Exception('Error')
# with open(sample_path, "wb") as f:
# f.write(response.content)
encrypt_path, private_key_pem = encrypt_file(sample_path)
decrypt_path = decrypt_file(encrypt_path, private_key_pem)
main()
现在你可以看到结果:
Encrypting with public key (1613, 3233)
Origin bytes b'PK\x03\x04\x14\x00\x08\x08\x08\x00\xa6c\x10K\x00'
Cipher integers [2730, 658, 3077, 2601, 497, 0, 220, 220, 220, 0, 2869, 2590, 1765, 658, 0]
Cipher bytes b'\n\xaa\x02\x92\x0c\x05\n)\x01\xf1\x00\x00\x00\xdc\x00'
File encrypted successfully.
Decrypting with private key (677, 3233)
Cipher bytes b'\n\xaa\x02\x92\x0c\x05\n)\x01\xf1\x00\x00\x00\xdc\x00'
Cipher integers [2730, 658, 3077, 2601, 497, 0, 220, 220, 220, 0, 2869, 2590, 1765, 658, 0]
Origin bytes b'PK\x03\x04\x14\x00\x08\x08\x08\x00\xa6c\x10K\x00'
File decrypted successfully.
但问题是,1MB文件加密到2.1MB(2倍),甚至RSA密钥也非常慢,这是一个非常简单的数字,所以这就是为什么我们不应该使用RSA。相反,AES是要走的路,您也可以将RSA与AES密钥结合起来以提高安全性,但我不会让事情变得复杂。
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
import os
PREVIEW_LENGTH = 15
def encrypt(bytes, aes_key, iv):
cipher = Cipher(algorithms.AES(aes_key), modes.CFB(iv), backend=default_backend())
# Encrypt the large file with AES
encryptor = cipher.encryptor()
cipher_bytes = encryptor.update(bytes) + encryptor.finalize()
print('Encrypting with aes_key', aes_key)
print('Origin bytes', bytes[:PREVIEW_LENGTH])
print('Cipher bytes', cipher_bytes[:PREVIEW_LENGTH])
return cipher_bytes
def decrypt(cipher_bytes, aes_key, iv):
# Create an AES cipher object with the AES key and IV
cipher = Cipher(algorithms.AES(aes_key), modes.CFB(iv), backend=default_backend())
# Decrypt the encrypted file with AES
decryptor = cipher.decryptor()
decrypted_bytes = decryptor.update(cipher_bytes) + decryptor.finalize()
print('Decrypting with aes key', aes_key)
print('Cipher bytes', cipher_bytes[:PREVIEW_LENGTH])
print('Origin bytes', decrypted_bytes[:PREVIEW_LENGTH])
return decrypted_bytes
def generate_key():
# Generate a random 256-bit AES key
aes_key = os.urandom(32)
iv = os.urandom(16)
return aes_key, iv
def encrypt_file(filepath):
aes_key, iv = generate_key()
with open(filepath, "rb") as f:
bytes = f.read()
encrypted_data = encrypt(bytes, aes_key, iv)
encrypted_filepath = filepath + ".encrypted"
with open(encrypted_filepath, "wb") as f:
f.write(encrypted_data)
print("File encrypted successfully.")
return encrypted_filepath, aes_key, iv
def decrypt_file(filepath, aes_key, iv):
with open(filepath, "rb") as f:
encrypted_data = f.read()
decrypted_data = decrypt(encrypted_data, aes_key, iv)
# Create a decrypted file with a ".decrypted" extension
decrypted_filepath = filepath.replace('.encrypted', '') # Remove ".encrypted" from the end of the file name
decrypted_filepath = 'decrypted_' + decrypted_filepath
with open(decrypted_filepath, "wb") as f:
f.write(decrypted_data)
print("File decrypted successfully.")
return decrypted_filepath
def main():
sample_path = 'file-sample_1MB.docx'
# Download sample for testing purpose, comment this if you already have a file
# import requests
# url = "https://file-examples.com/storage/fe805ba0cc65378da968c5c/2017/02/file-sample_1MB.docx"
# response = requests.get(url)
# if response.status_code != 200:
# raise Exception('Error')
# with open(sample_path, "wb") as f:
# f.write(response.content)
encrypt_path, aes_key, iv = encrypt_file(sample_path)
decrypt_path = decrypt_file(encrypt_path, aes_key, iv)
main()
结果快速、简单:
Encrypting with aes_key b"\xe1\xea\xbc~tP\xab\x00\\'Uf\xe8\x87|\xdd\xa0\x965\x0e\x88\n\xb3\xb4\xb8\xb4\r\xde\x00c\x0e\xf9"
Origin bytes b'PK\x03\x04\x14\x00\x08\x08\x08\x00\xa6c\x10K\x00'
Cipher bytes b'G\xb9B\xdeK\xedG\x9a\xcd_-\x9ebl\x07'
File encrypted successfully.
Decrypting with aes key b"\xe1\xea\xbc~tP\xab\x00\\'Uf\xe8\x87|\xdd\xa0\x965\x0e\x88\n\xb3\xb4\xb8\xb4\r\xde\x00c\x0e\xf9"
Cipher bytes b'G\xb9B\xdeK\xedG\x9a\xcd_-\x9ebl\x07'
Origin bytes b'PK\x03\x04\x14\x00\x08\x08\x08\x00\xa6c\x10K\x00'
File decrypted successfully.
评论