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.
Note: It is important to understand the difference between encryption and hashing algorithms, in encryption, you can retrieve the original data once you have the key, where in hashing functions, you cannot, that's why they're called one-way encryption.
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
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()
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()
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)
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.
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:
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.
Also, if you're interested in cryptography, I would personally suggest you read Serious Cryptography book, as it is very suitable for you and not very mathematically detailed.
Happy Coding ♥View Full Code