#python #encryption #cryptography #bcrypt #encryption-symmetric
Вопрос:
Здравствуйте, я создаю менеджер паролей и хочу зашифровать файл пароля, поэтому я генерирую и создаю первый пароль, а когда я его читаю и расшифровываю, он его считывает. А затем при создании другого пароля он создает его, но затем при расшифровке выдает ошибку. Из того, что я вижу, я использую тот же ключ. Вот код:
#imports
import random,string,os,sys
from cryptography.fernet import Fernet
import bcrypt
if os.path.isfile('salt.txt'):
#Gets the salt
with open('salt.txt','rb') as saltfile:
salt = saltfile.read()
else:
with open('salt.txt','wb')as saltfile:
salt = bcrypt.gensalt()
saltfile.write(salt)
saltfile.close()
#Hashes the item
def hashPass(item):
global passwordOut
hashed = bcrypt.hashpw(item,salt)
passwordOut = hashed
return passwordOut
#Password Generator
def setPassword(length=30,char=string.ascii_letters string.digits string.punctuation):
global generatedPassword
generatedPassword= ''.join(random.choice(char) for x in range(length))
return generatedPassword
if os.path.isfile('mykey.key') == True:
#Opens the key
with open('mykey.key', 'rb') as mykey:
print('True')
key = mykey.read()
f = Fernet(key)
mykey.close()
elif os.path.isfile('mykey.key')== False:
print('False')
# Generates a kay
key = Fernet.generate_key()
# Writes a new key
with open('mykey.key', 'wb') as mykey:
mykey.write(key)
f = Fernet(key)
mykey.close()
#Sets the key
#Stating initalization
print("Hello and welcome to your password manager!")
while True:
#If there is a user file
if os.path.isfile('user.txt'):
#Read the user file
with open('user.txt','rb') as user_file:
file = user_file.read()
#Gets the inputs
getUser = input("Enter your username ").encode('utf-8')
getPass = input('Enter your password: ').encode('utf-8')
#Hashes the inputs through the hashing funcion
hashPass(item=getUser)
usr = passwordOut
hashPass(item=getPass)
passw = passwordOut
#If the users hashed input is the same in the users file it carries on with the procedure
if usr in file and passw in file:
while True:
print("""Pick from the list of what you want to do:
1. Generate a new password
2. See passwords
3. Quit""")
usrinput = int(input('Enter a number from the menu: '))
if usrinput == 1:
print("nGenerating password...")
setPassword()
usrinput = input("What is the password for: ")
splitter = ': '
#
if os.path.isfile('passwordenc.txt'):
with open('passwordenc.txt','ab')as password_file:
var = usrinput splitter generatedPassword 'n'
encrypted = f.encrypt(bytes(var.encode('utf-8')))
password_file.write(encrypted)
print("Your new password for: " usrinput)
print("And the password is: " generatedPassword)
password_file.close()
else:
with open('passwordenc.txt','wb')as password_file:
var = usrinput splitter generatedPassword 'n'
encrypted = f.encrypt(bytes(var.encode('utf-8')))
password_file.write(encrypted)
print("Your new password for: " usrinput)
print("And the password is: " generatedPassword)
password_file.close()
if usrinput == 2:
if os.path.isfile('passwordenc.txt'):
with open('passwordenc.txt','rb') as password_file:
read = password_file.read()
decrypt = f.decrypt(read)
print(decrypt)
password_file.close()
else:
print('File not found! Need to create a new file.')
if usrinput == 3:
quit()
#If not the same it loops back around
else:
print("nUser not found!n")
#If there is no file:
else:
#Gets a user input
username = input('Enter a username: ').encode('utf-8')
password = input('Enter a password, cannot be changed! ').encode('utf-8')
#Hashes the user input
hashPass(item=username)
usr = passwordOut
hashPass(item=password)
passw = passwordOut
#Writes the user input
with open('user.txt','wb') as user:
user.write(usr)
user.write(passw)
print('nUser has been created!n')
Вот код терминала:
C:UsersJamesDocumentspasswordsvenvScriptspython.exe C:/Users/James/Documents/passwords/main.py
True
Hello and welcome to your password manager!
Enter your username james
Enter your password: Kaits_1204
Pick from the list of what you want to do:
1. Generate a new password
2. See passwords
3. Quit
Enter a number from the menu: 2
Traceback (most recent call last):
File "C:UsersJamesDocumentspasswordsvenvlibsite-packagescryptographyfernet.py", line 119, in _verify_signature
h.verify(data[-32:])
File "C:UsersJamesDocumentspasswordsvenvlibsite-packagescryptographyhazmatprimitiveshmac.py", line 74, in verify
ctx.verify(signature)
File "C:UsersJamesDocumentspasswordsvenvlibsite-packagescryptographyhazmatbackendsopensslhmac.py", line 75, in verify
raise InvalidSignature("Signature did not match digest.")
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/James/Documents/passwords/main.py", line 106, in <module>
decrypt = f.decrypt(read)
File "C:UsersJamesDocumentspasswordsvenvlibsite-packagescryptographyfernet.py", line 80, in decrypt
return self._decrypt_data(data, timestamp, time_info)
File "C:UsersJamesDocumentspasswordsvenvlibsite-packagescryptographyfernet.py", line 137, in _decrypt_data
self._verify_signature(data)
File "C:UsersJamesDocumentspasswordsvenvlibsite-packagescryptographyfernet.py", line 121, in _verify_signature
raise InvalidToken
cryptography.fernet.InvalidToken
Process finished with exit code 1
Ответ №1:
Проблема в том, что вы вводите пользователя для выбранного пароля учетной записи, а затем добавляете разделитель и случайно сгенерированный пароль '/n'
. После этого вы зашифруете это var
с помощью fernet
. Этот метод будет работать для просмотра вашей первой пароль, поскольку с первой пароль, который вы читать и расшифровать весь файл, но не с несколькими пароли в зашифрованном виде, поскольку каждый var
шифрование-это уникальные (не имеющие разные IV
), что означает, что для расшифровки всех паролей, вам нужен способ, чтобы сигнализировать о конце зашифрованный пароль и начало другой, зашифрованный пароль, так что вы передаете ferent
правильный текст с правильным поля. Это можно сделать, просто добавив --END OF PASSWORD--
после каждого шифрования запись в файл пароля. Затем во время считывания паролей вы можете просто разделить файл pass на эти поля и передать результат в fernet.
ПРИМЕЧАНИЕ: не используйте этот код в качестве менеджера паролей, так как, хотя вы шифруете свои пароли, вы оставляете свой мастер-пароль в mykey.key
незашифрованном виде, что делает это совершенно бесполезным.
import random,string,os,sys
from cryptography.fernet import Fernet
import bcrypt
if os.path.isfile('salt.txt'):
#Gets the salt
with open('salt.txt','rb') as saltfile:
salt = saltfile.read()
else:
with open('salt.txt','wb')as saltfile:
salt = bcrypt.gensalt()
saltfile.write(salt)
#saltfile.close() # You dont need to close
#Hashes the item
def hashPass(item):
global passwordOut
hashed = bcrypt.hashpw(item,salt)
passwordOut = hashed
# return passwordOut
# Random Password Generator
def setPassword(length=30,char=string.ascii_letters string.digits string.punctuation):
global generatedPassword
generatedPassword= ''.join(random.choice(char) for x in range(length))
return generatedPassword
if os.path.isfile('mykey.key') == True:
#Opens the key
with open('mykey.key', 'rb') as mykey:
print('True')
key = mykey.read()
f = Fernet(key)
elif os.path.isfile('mykey.key')== False:
print('False')
# Generates a kay
key = Fernet.generate_key()
# Writes a new key
with open('mykey.key', 'wb') as mykey:
mykey.write(key)
f = Fernet(key)
#mykey.close() # with doesnt need file to be closed
#Sets the key
#Stating initalization
print("Hello and welcome to your password manager!")
while True:
#If there is a user file
if os.path.isfile('user.txt'):
#Read the user file
with open('user.txt','rb') as user_file:
file = user_file.read()
print("File ", file)
#Gets the inputs
getUser = input("Enter your username ").encode('utf-8')
getPass = input('Enter your password: ').encode('utf-8')
#Hashes the inputs through the hashing funcion
hashPass(item=getUser)
usr = passwordOut
hashPass(item=getPass)
passw = passwordOut
#If the users hashed input is the same in the users file it carries on with the procedure
if usr in file and passw in file:
while True:
print("""Pick from the list of what you want to do:
1. Generate a new password
2. See passwords
3. Quit""")
usrinput = int(input('Enter a number from the menu: '))
if usrinput == 1:
print("nGenerating password...")
setPassword()
usrinput = input("What is the password for: ")
splitter = ': '
#
if os.path.isfile('passwordenc.txt'):
with open('passwordenc.txt','ab')as password_file:
var = usrinput splitter generatedPassword 'n'
encrypted = f.encrypt(bytes(var.encode('utf-8')))
password_file.write(encrypted)
password_file.write(b"--END OF PASSWORD--")
print("Your new password for: " usrinput)
print("And the password is: " generatedPassword)
else:
with open('passwordenc.txt','wb')as password_file:
var = usrinput splitter generatedPassword 'n'
encrypted = f.encrypt(bytes(var.encode('utf-8')))
password_file.write(encrypted)
password_file.write(b"--END OF PASSWORD--")
print("Your new password for: " usrinput)
print("And the password is: " generatedPassword)
if usrinput == 2:
if os.path.isfile('passwordenc.txt'):
with open('passwordenc.txt','r') as password_file:
whole_file = password_file.read()
password_list = whole_file.split("--END OF PASSWORD--")
for password in password_list:
if password:
decrypt = f.decrypt(bytes(password, encoding="utf-8"))
print("Decrypted pass: ", decrypt)
else:
print('File not found! Need to create a new file.')
if usrinput == 3:
quit()
#If not the same it loops back around
else:
print("nUser not found!n")
#If there is no file:
else:
#Gets a user input
username = input('Enter a username: ').encode('utf-8')
password = input('Enter a password, cannot be changed! ').encode('utf-8')
#Hashes the user input
hashPass(item=username)
usr = passwordOut
hashPass(item=password)
passw = passwordOut
#Writes the user input
with open('user.txt','wb') as user:
user.write(usr)
user.write(passw)
print('nUser has been created!n')
Комментарии:
1. Но как бы я зашифровал ключевой файл и расшифровал его?
2. @Mr_Westhead у вас есть 2 варианта: либо вы можете каким-то образом использовать пароль, который пользователь должен вводить каждый раз, чтобы расшифровать главный ключ. ИЛИ вы можете использовать пароль в качестве ввода для функции вывода ключа, такой как PBKDF2, которая преобразует пароль в случайные биты, которые вы можете использовать для расшифровки базы данных паролей. Идея заключается в том, что вы НЕ храните главный ключ без какого-либо шифрования, поэтому вы либо защищаете его с помощью пароля, предоставленного пользователем, либо генерируете этот главный ключ во время выполнения .