How to Encrypt and Decrypt Files in Python

Abdou Rockikz · 26 sep 2019

Abdou Rockikz · 5 min read · Updated nov 2019 · Ethical Hacking

Encryption is the process of encoding an information in such a way that only authorized parties can access it. It is critically important because it allows you to securely protect data that you don't want anyone to see or access it.

In this tutorial, you will learn how to use Python to encrypt files or any byte object (also string objects) using cryptography library.

We will be using symmetric encryption, which means the same key we used to encrypt data, is also usable for decryption. There are a lot of encryption algorithms out there, the library we gonna use is built on top of AES algorithm.

RELATED: How to Download Files in Python.

Let's start off by installing cryptography:

pip3 install cryptography

Open up a new Python file and let's get started:

from cryptography.fernet import Fernet
import os

Generating the Key

Fernet is an implementation of symmetric authenticated cryptography, let's start by generating that key and write it to a file:

def write_key():
    """
    Generates a key and save it into a file
    """
    key = Fernet.generate_key()
    with open("key.key", "wb") as key_file:
        key_file.write(key)

generate_key() function generates a fresh fernet key, you really need to keep this in a safe place, if you lose the key, you will no longer be able to decrypt data that was encrypted with this key.

Since this key is unique, we won't be generating the key each time we encrypt anything, so we need a function to load that key for us:

def load_key():
    """
    Loads the key from the current directory named `key.key`
    """
    return open("key.key", "rb").read()

String Encryption

Now that we know how to get the key, let's start by encrypting string objects, just to make you familiar with it first.

Generating and writing the key to a file:

# generate and write a new key
write_key()

Let's load that key:

# load the previously generated key
key = load_key()

Some message:

message = "some secret message".encode()

We need to encode strings, to convert them to bytes to be suitable for encryption, encode() method encodes that string using utf-8 codec. Initializing the Fernet class with that key:

# initialize the Fernet class
f = Fernet(key)

Encrypting the message:

# encrypt the message
encrypted = f.encrypt(message)

f.encrypt() method encrypts the data passed, the result of this encryption is known as a "Fernet token" and has strong privacy and authenticity guarantees.

Let's see how it looks:

# print how it looks
print(encrypted)

Output:

b'gAAAAABdjSdoqn4kx6XMw_fMx5YT2eaeBBCEue3N2FWHhlXjD6JXJyeELfPrKf0cqGaYkcY6Q0bS22ppTBsNTNw2fU5HVg-c-0o-KVqcYxqWAIG-LVVI_1U='

Decrypting that:

decrypted_encrypted = f.decrypt(encrypted)
print(decrypted_encrypted)
b'some secret message'

That's indeed, the same message.

f.decrypt() method decrypts a Fernet token. This will return the original plaintext as the result when it's successfully decrypted, otherwise it'll raise an exception.

File Encryption

Now you know how to basically encrypt strings, let's dive into file encryption, we need a function to encrypt a file given the name of file and key:

def encrypt(filename, key):
    """
    Given a filename (str) and key (bytes), it encrypts the file and write it
    """
    f = Fernet(key)

After initializing the Fernet object with the given key, let's read that file first:

    with open(filename, "rb") as file:
        # read all file data
        file_data = file.read()

After that, encrypting the data we just read:

    # encrypt data
    encrypted_data = f.encrypt(file_data)

Writing the encrypted file with the same name, so it will override the original (don't use this on a sensitive information yet, just test on some junk data):

    # write the encrypted file
    with open(filename, "wb") as file:
        file.write(encrypted_data)

Okey that's done, going to the decryption function now, it is the same process except we will use decrypt() function instead of encrypt():

def decrypt(filename, key):
    """
    Given a filename (str) and key (bytes), it decrypts the file and write it
    """
    f = Fernet(key)
    with open(filename, "rb") as file:
        # read the encrypted data
        encrypted_data = file.read()
    # decrypt data
    decrypted_data = f.decrypt(encrypted_data)
    # write the original file
    with open(filename, "wb") as file:
        file.write(decrypted_data)

Let's test this, I have a csv file and a key in the current directory, as shown in the following figure:

File to encrypt

It is completely readable file, to encrypt it, all we need to do is call the function we just wrote:

# uncomment this if it's the first time you run the code, to generate the key
# write_key()
# load the key
key = load_key()
# file name
file = "data.csv"
# encrypt it
encrypt(file, key)

Once you execute this, you may see the file increased in size, and it's junk data, you can't even read a single word!

To get the file back into the original form, just call decrypt() function:

# decrypt the file
decrypt(file, key)

That's it! You'll see the original file appears in place of the encrypted previously.

Check cryptography's official documentation for further details and instructions.

Note though, you need to beware of large files, as the file will need to be completely on memory to be suitable for encryption, you need to consider some methods of splitting the data or file compression for large files!

Here is the full code after some refactoring, I just made it easy to run as scripts.

READ ALSOHow to Download All Images from a Web Page in Python.

Happy Coding ♥

View Full Code
Sharing is caring!


Read Also





Comment panel

   
Comment system is still in Beta, if you find any bug, please consider contacting us here.