-1

Hello so I am making a password manager and I want to encrypt the password file, so I generate and create the first password and when I read it and decrypt it reads it. And then when making another password it creates it but then when decrypting it throws an error. From what I can see I am using the same key. Here is the code:

#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')

Here is the terminal code:

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

1 Answers1

0

The problem is that you take input of user for chosen account password then you append splitter and random generated password then '/n'. After that you encrypt this var using fernet. This method will work to view your first password since with first password you read and decrypt whole file but not with multiple encrypted passwords since each var encryption is unique (having different IV) which means that to decrypt all the passwords you will need a way to signal the end of an encrypted password and beginning of another encrypted password so that you pass to ferent the correct ciphertext with correct margins. This can be done by simply adding --END OF PASSWORD-- after each encryption write to password file. Then during reading of passwords you can just split pass file on these margins and pass result to fernet.

NOTE: dont use this code as your password manager since although you encrypt your passwords you are leaving your master password in mykey.key unencrypted which makes this totally useless.

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')
KMG
  • 1,433
  • 1
  • 8
  • 19
  • But how would I encrypt the key file and decrypt it? –  Mar 27 '21 at 13:22
  • 1
    @Mr_Westhead you have 2 options either you can use a password in some way that the user must enter each time to decrypt the master key. OR you can use the password as input to key derivation function such as PBKDF2 that will convert the password to random bits which you can use to decrypt password database. The idea is that you DONT store the master key without any encryption, so you either protect it using user supplied password, or you generate this master key at run time . – KMG Mar 27 '21 at 16:06