почему я получаю недействительный код шифрования fernet при использовании одного и того же ключа

#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, которая преобразует пароль в случайные биты, которые вы можете использовать для расшифровки базы данных паролей. Идея заключается в том, что вы НЕ храните главный ключ без какого-либо шифрования, поэтому вы либо защищаете его с помощью пароля, предоставленного пользователем, либо генерируете этот главный ключ во время выполнения .