如何使用Fernet加密库修复解密函数
我正在尝试创建一个程序,它可以接收标题、笔记和主密码,然后使用Python对这些信息进行加密或解密。但是,当我尝试用decrypt_notes这个函数来解密信息时,它显示“解密失败。主密码不正确”的错误,提示是InvalidToken。请问我该如何解决这个问题?
from tkinter import *
from tkinter import messagebox
import base64
import os
from cryptography.fernet import Fernet, InvalidToken
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
window = Tk()
window.title("Secret Notes")
window.minsize(width=400, height=400)
window.config(padx=20, pady=20)
title_label = Label(text="Enter the Title")
title_label.config(fg="black", padx=10, pady=10)
title_label.pack()
title_entry = Entry(width=30)
title_entry.focus()
title_entry.pack()
secret_label = Label(text="Enter the Secret Message")
secret_label.config(fg="black", padx=10, pady=10)
secret_label.pack()
secret_text = Text(width=30, height=10)
secret_text.pack()
masterkey_label = Label(text="Enter the Key")
masterkey_label.config(fg="black", padx=10, pady=10)
masterkey_label.pack()
masterkey_entry = Entry(width=30, show="*")
masterkey_entry.pack()
desktop_path = os.path.join(os.path.join(os.environ['USERPROFILE']), 'Desktop')
title = title_entry.get()
secret = secret_text.get("1.0", "end-1c")
streaky = masterkey_entry.get()
def save_and_encrypt():
title = title_entry.get()
secret = secret_text.get("1.0", END)
streaky = masterkey_entry.get()
if len(title) == 0 or len(secret) == 0 or len(streaky) == 0:
messagebox.showerror(title="Error", message="Please fill in all fields.")
else:
password = streaky.encode()
salt = os.urandom(16)
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=480000,
)
key = base64.urlsafe_b64encode(kdf.derive(password))
f = Fernet(key)
encrypted_text = secret.encode()
token1 = f.encrypt(encrypted_text)
with open(os.path.join(desktop_path, "encrypted_notes.txt"), "a") as file:
file.write(f"Title: {title}\n")
file.write(f"Encrypted Message: {token1}\n")
file.write("\n")
messagebox.showinfo(title="Completed", message="Your note has been saved and encrypted.")
def decrypt_notes():
# Get the master key from the entry widget
master_key = masterkey_entry.get()
# Read the encrypted notes from the file
with open(os.path.join(desktop_path, "encrypted_notes.txt"), "r") as file:
lines = file.readlines()
# Iterate through lines to find the encrypted message corresponding to the title
encrypted_message = None
for i in range(0, len(lines), 3): # Assuming each note is 3 lines (title, encrypted message, blank line)
title_line = lines[i]
if title_line.strip() == f"Title: {title}":
encrypted_message_line = lines[i + 1]
encrypted_message = encrypted_message_line.split("Encrypted Message: ")[1].strip()
break
if encrypted_message is None:
messagebox.showerror(title="Error", message="Note not found.")
return
# Decode the master key and decrypt the message
try:
password = master_key.encode()
salt = os.urandom(16)
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=480000,
)
key = base64.urlsafe_b64encode(kdf.derive(password))
f = Fernet(key)
decrypted_message = f.decrypt(encrypted_message.encode()).decode()
# Show the decrypted message
messagebox.showinfo(title="Decrypted Message", message=decrypted_message)
except (InvalidToken, ValueError):
messagebox.showerror(title="Error", message="Decryption failed. Incorrect master key.")
save_button = Button(text="Save & Encrypt",command=save_and_encrypt)
save_button.config(padx=1, pady=1)
save_button.pack(padx=(10, 0), pady=(10, 0))
decrypt_button = Button(text="Decrypt",command=decrypt_notes)
decrypt_button.config(padx=1, pady=1)
decrypt_button.pack(padx=(10, 0), pady=(10, 0))
window.mainloop()
不幸的是,我找不到解决办法。
1 个回答
0
这里有几个问题:
- 使用不同的盐值会生成不同的主密钥来进行加密和解密。要使用相同的盐值。
save_and_encrypt()
函数里的token1
应该是字符串,而不是字节。decrypt_notes()
函数里应该读取title
。
需要的修改:
...
# don't need to get the values here as they are all empty strings
#title = title_entry.get()
#secret = secret_text.get("1.0", "end-1c")
#streaky = masterkey_entry.get()
# create the salt
salt = b'some.secret.salt'
def save_and_encrypt():
...
else:
...
#salt = os.urandom(16) # don't generate random salt here
...
token1 = f.encrypt(encrypted_text).decode() # make token1 a string, not bytes
...
...
def decrypt_notes():
# read title here
title = title_entry.get()
...
try:
...
#salt = os.urandom(16) # don't generate random salt here
...
...