[python]Keeping encryption key and decrypt the file anytime

This is a follow up from the previous post of this code in https://cyruslab.net/2019/08/17/pythonsample-encrypting-and-decrypting-the-dictionary/

The code snippet is a sample to demonstrate encrypting and decrypting the entire dictionary in a file, however there is a problem with this snippet. if the encryption and decryption is done within the same “session” there is no issue, however if you have encrypted a file and decrypt the file again later you will get an exception raised by Fernet, this is because everytime you run a key is generated again, the previous session already generated a key to encrypt, however if the script is to run again a different key will be generated and hence cannot decrypt the previously encrypted file.

So a feasible solution is to generate a symmetric key and save the key as a file, this key is to be used for decrypting the encrypted file later.

from getpass import getpass
import logging
from cryptography.fernet import Fernet
import json
from os.path import exists

logging.basicConfig(level=logging.DEBUG)


# get credential returns dictionary
def get_creds():
    username = input("Username: ")
    password = getpass()
    return {"username": username,
            "password": password}


# For encrypting and descrypting file, mode=1 is encrypt which is default, 0 is decrypt.
def cred_file_security(cipher, filename, creds=None, mode=1):
    byte_string = json.dumps(creds).encode('utf-8')
    # print(byte_string)
    byte_ciphertext = cipher.encrypt(byte_string)
    if mode == 1:
        with open(filename, "wb") as encrypt_file:
            encrypt_file.write(byte_ciphertext)
            return "credential is encrypted in {}".format(filename)
    elif mode == 0:
        print("Decrypting file...")
        with open(filename, "rb") as decrypt_file:
            data = decrypt_file.read()
            # print(data)
        decrypted_data = cipher.decrypt(data).decode('utf-8')
        return decrypted_data
    else:
        return "{} cannot be opened!!".format(filename)


if __name__ == "__main__":
    # Fernet key generation, if the key is not present
    # enc.key is the key for encrypting and decrypting keep it safe.
    if not exists("enc.key"):
        key = Fernet.generate_key()
        with open("enc.key", "wb") as key_file:
            key_file.write(key)
    # If the key already exists, open the key and use the key to create a cipher
    with open("enc.key", "rb") as read_key_file:
        key_file = read_key_file.read()
    # use the cipher to encrypt and decrypt for later.
    cipher = Fernet(key_file)
    # change the encrypted filename anytime.
    filename = "creds.enc"
    if not exists(filename):
        file_response = cred_file_security(cipher, filename, creds=get_creds(), mode=1)
        print(file_response)
    else:
        file_response = cred_file_security(cipher, filename, mode=0)
        print(file_response)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s