为什么我在使用相同的密钥时得到加密 fernet InvalidToken

why am I getting cryptography fernet InvalidToken when using the same key

你好,我正在制作一个密码管理器,我想加密密码文件,所以我生成并创建了第一个密码,当我读取和解密时,它会读取它。然后在创建另一个密码时它会创建它但是在解密时它会抛出错误。据我所知,我正在使用相同的密钥。 这是代码:

#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:\Users\James\Documents\passwords\venv\Scripts\python.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:\Users\James\Documents\passwords\venv\lib\site-packages\cryptography\fernet.py", line 119, in _verify_signature
    h.verify(data[-32:])
  File "C:\Users\James\Documents\passwords\venv\lib\site-packages\cryptography\hazmat\primitives\hmac.py", line 74, in verify
    ctx.verify(signature)
  File "C:\Users\James\Documents\passwords\venv\lib\site-packages\cryptography\hazmat\backends\openssl\hmac.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:\Users\James\Documents\passwords\venv\lib\site-packages\cryptography\fernet.py", line 80, in decrypt
    return self._decrypt_data(data, timestamp, time_info)
  File "C:\Users\James\Documents\passwords\venv\lib\site-packages\cryptography\fernet.py", line 137, in _decrypt_data
    self._verify_signature(data)
  File "C:\Users\James\Documents\passwords\venv\lib\site-packages\cryptography\fernet.py", line 121, in _verify_signature
    raise InvalidToken
cryptography.fernet.InvalidToken

Process finished with exit code 1

问题是您输入用户选择的帐户密码,然后附加拆分器和随机生成的密码,然后 '/n'。之后,您使用 fernet 加密此 var。此方法将用于查看您的第一个密码,因为使用第一个密码您可以读取和解密整个文件,但不能使用多个加密密码,因为每个 var 加密都是唯一的(具有不同的 IV),这意味着要解密所有您将需要一种方法来指示加密密码的结尾和另一个加密密码的开头,以便您传递给 ferent 具有正确边距的正确密文。这可以通过在每次加密写入密码文件后简单地添加 --END OF PASSWORD-- 来完成。然后在读取密码期间,您可以在这些边距上拆分传递文件并将结果传递给 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')