Ошибка Signature did not match digest и cryptography.fernet.InvalidToken при шифровании пароля
Делаю проект менеджера паролей с шифрованием паролей. Остановился на окне с вводом мастер-пароля. Ошибка заключается в том, что при перезапуске кода Fernet пишет о том, что подпись не соответствует чему-то, а также что сам ключ недействителен. Однако я почти полностью уверен что ключ никак не изменяется и хранится в файле key.key. Обновляется ключ только вручную, если использовать "восстановление пароля", причем после этой операции ключ подтверждается и приложение открывает следующий файл с основным кодом приложения.
from tkinter import *
from tkinter import messagebox
import os
from cryptography.fernet import Fernet
root = Tk()
root.title('Авторизация')
root.geometry('925x500+300+200')
root.config(bg="#fff")
root.resizable(False, False)
Flag = False
# ---------Sign in Function-----------
def signin():
global Flag, code
password = code.get()
with open('stcn.txt', 'r') as f:
data = f.readline().rstrip()
f.close()
anc = fer.decrypt(data.encode()).decode()
print(anc)
if anc == password:
Flag = True
root.destroy()
else:
messagebox.showerror("Ошибка", "Введите верный пароль \n"
"При первом входе в систему воспользуйтесь восстановлением пароля")
# ---------Image Here----------
img = PhotoImage(file='images/login.png')
Label(root, image=img, bg='white').place(x=50, y=50)
# ------------Frame-------------
frame = Frame(root, width=350, height=350, bg='white')
frame.place(x=480, y=70)
heading = Label(frame, text='Авторизация', fg='#57a1f8', bg='white',
font=('Microsoft YaHei UI Light', 23, 'bold'))
heading.place(x=100, y=5)
info = Label(frame, text="Введите текущий мастер-пароль", fg="Black", bg="white")
info.place(x=25, y=180)
# ------------Password Functions------------
def on_enter(e):
code.delete(0, 'end')
def on_leave(e):
cname = code.get()
if cname == '':
code.insert(0, 'Пароль')
def delall():
res = messagebox.askokcancel(title="Удалить все сохранённые пароли?",
message="Если вы забыли мастер-пароль, или хотите создать новый, то приложение не сможет расшифровать сохранённые пароли. \n \n"
"В этом случае можно только удалить все сохраненные в базе данных пароли и создать новый мастер-пароль. \n \n"
"НАЖМИТЕ 'ОК', ЕСЛИ ХОТИТЕ УДАЛИТЬ ВСЕ ПАРОЛИ")
if res:
os.remove("PasswordEncrMngr.db")
r = open("PasswordEncrMngr.db", "w+")
r.close()
messagebox.showinfo("Учетные данные удалены", "Все учетные данные удалены")
pwdwnd = Tk()
pwdwnd.title("Создание нового мастер-пароля")
pwdwnd.config(bg='white', border=0)
pwdwnd.geometry("400x150")
pwdwnd.wm_attributes('-alpha')
# def onpwdentry(evt):
# write_key()
# scnt = pwdbox.get()
# with open('stcn.txt', 'a') as f:
# f.write(fer.encrypt(scnt.encode()).decode() + "\n")
# f.close()
# pwdwnd.destroy()
def onokclick():
write_key()
scnt = pwdbox.get()
with open('stcn.txt', 'w') as f:
f.write(fer.encrypt(scnt.encode()).decode())
f.close()
pwdwnd.destroy()
Label(pwdwnd, text='Введите новый мастер-пароль', font=('Microsoft YaHei UI Light', 16, 'bold'),
bg='white').place(x=40, y=20)
pwdbox = Entry(pwdwnd, show='*', fg="black", border=0, bg="white", width=30,
font=('Microsoft YaHei UI Light', 11))
pwdbox.place(x=80, y=70)
Frame(pwdwnd, width=250, height=2, bg='black').place(x=75, y=95)
Button(pwdwnd, command=onokclick, text='Сохранить новый пароль', border=0, background='#57a1f8', width=22,
height=1).place(x=130, y=110)
else:
pass
def write_key():
global key
key = Fernet.generate_key()
with open("key.key", "wb") as key_file:
key_file.write(key)
def load_key():
global key
file = open("key.key", 'rb')
key = file.read()
file.close()
return key
# write_key()
key = load_key()
fer = Fernet(key)
print(key)
# -----------------------------------
code = Entry(frame, width=30, fg='black', show="•", border=0,
bg='white', font=('Microsoft YaHei UI Light', 11))
code.place(x=30, y=150)
code.bind('<FocusIn>', on_enter)
code.bind('<FocusOut>', on_leave)
Frame(frame, width=295, height=2, bg='black').place(x=25, y=177)
# ----------------------------------
Button(frame, width=39, pady=7, text='Продолжить',
bg='#57a1f8', fg='white', border=0, command=signin).place(x=35, y=204)
sign_up = Button(frame, width=39, text='Не помню пароль или создать новый', border=0,
bg='white', cursor='hand2', fg='#57a1f8', command=delall)
sign_up.place(x=40, y=250)
root.mainloop()
Вот такая ошибка выходит при выполнении кода:
Exception in Tkinter callback
Traceback (most recent call last):
File "EncryptManager\.venv\Lib\site-packages\cryptography\fernet.py", line 130, in _verify_signature
h.verify(data[-32:])
cryptography.exceptions.InvalidSignature: Signature did not match digest.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 1967, in __call__
return self.func(*args)
^^^^^^^^^^^^^^^^
File "C:\Users\Файлы\ДГТУ\Учебная ознакомительная практика\Проект\EncryptManager\welcome.py", line 25, in signin
anc = fer.decrypt(data.encode()).decode()
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "EncryptManager\.venv\Lib\site-packages\cryptography\fernet.py", line 89, in decrypt
return self._decrypt_data(data, timestamp, time_info)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "EncryptManager\.venv\Lib\site-packages\cryptography\fernet.py", line 148, in _decrypt_data
self._verify_signature(data)
File "EncryptManager\.venv\Lib\site-packages\cryptography\fernet.py", line 132, in _verify_signature
raise InvalidToken
cryptography.fernet.InvalidToken
Пробовал менять способы чтения и записи файлов при сохранении ключа и исходного пароля, изменяя атрибуты open() Проверял логику кода на шифрование/дешифрование, но что-то не выходит...
Ответы (1 шт):
Такая же проблема! Все храню в бинарном виде в БД постгрес, ключ один, его уже текстом вписал вместо переменной. Если зашифровать и сразу отправить на дешифровку переменную, все хорошо работает, но если это делать разными командами то ерор!
from cryptography.fernet import Fernet
from config.data import CRIPTO_KEY
fernet = Fernet(b'xX8FN0tVdzXzgexIGQ9d51XMEIqnUiZQ2YSIohjCbFk=')
async def encrypt(data: str) -> bytes:
encrypted = fernet.encrypt(data.encode())
return encrypted
async def decrypt(encrypted_data: bytes) -> str:
print('encrypted_data = ', encrypted_data)
decrypted = fernet.decrypt(encrypted_data).decode()
return decrypted
вывод:
encrypted_data = b'gAAAAABmoB8uIq6bxP_NBAE5UIJBRkWHKPB4ddQepKN9vUNW5LaRQPW3YMJoc5QeeVsx5H48afLRjWPGDC3cXcr-VPRqm_S5sg=='
ошибка:
... lib/python3.10/site-packages/cryptography/fernet.py", line 118, in _get_unverified_token_data
raise InvalidToken
cryptography.fernet.InvalidToken