Before we get started, have you tried our new Python Code Assistant? It's like having an expert coder at your fingertips. Check it out!
Encryption is the process of encoding a piece of information so 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.
In this tutorial, you will learn how to use Python to encrypt files or any byte object (also string objects) using the cryptography library.
We will use 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 the AES algorithm.
There are many encryption uses in the real world. In fact, if you're reading this, then your browser is securely connected to this website (i.e., encryption). However, there are malicious uses of encryption, such as building ransomware; we have a tutorial on how to build such a tool. Check it out here.
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, whereas in hashing functions, you cannot; that's why they're called one-way encryption.
Table of contents:
RELATED: How to Extract and Decrypt Chrome Cookies in Python.
Let's start off by installing cryptography
:
Open up a new Python file, and let's get started:
Fernet is an implementation of symmetric authenticated cryptography; let's start by generating that key and writing it to a file:
The Fernet.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:
Now that we know how to generate, save and load 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:
Let's load that key:
Some message:
Since strings have the type of str
in Python, we need to encode them and convert them to bytes
to be suitable for encryption, the encode()
method encodes that string using the utf-8 codec. Initializing the Fernet
class with that key:
Encrypting the 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:
Output:
Decrypting that:
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.
Learn also: How to Encrypt and Decrypt PDF Files in Python.
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 the file and key:
After initializing the Fernet
object with the given key, let's read the target file first:
file_data
contains the data of the file, encrypting it:
Writing the encrypted file with the same name so it will override the original (don't use this on sensitive information yet; just test on some junk data):
Okay, that's done. Going to the decryption function now, it is the same process, except we will use the decrypt()
function instead of encrypt()
on the Fernet
object:
Let's test this. I have a data.csv
file and a key in the current directory, as shown in the following figure:
It is a completely readable file. To encrypt it, all we need to do is call the function we just wrote:
Once you execute this, you may see the file increased in size, and it's unreadable; you can't even read a single word!
To get the file back into the original form, just call the decrypt()
function:
That's it! You'll see the original file appears in place of the previously encrypted file.
Get: Ethical Hacking with Python EBook
Instead of randomly generating a key, what if we can generate the key from a password? Well, to be able to do that, we can use algorithms for this purpose.
One of these algorithms is Scrypt. It is a password-based key derivation function that was created in 2009 by Colin Percival; we will be using it to generate keys from a password.
If you want to follow along, create a new Python file and import the following:
First, key derivation functions need random bits added to the password before it's hashed; these bits are called the salt, which helps strengthen security and protect against dictionary and brute-force attacks. Let's make a function to generate that using the secrets
module:
We have a tutorial on generating random data. Make sure to check it out if you're unsure about the above cell.
Next, let's make a function to derive the key from the password and the salt:
We initialize the Scrypt algorithm by passing:
salt
.length
of the key (32 in this case).n
: CPU/Memory cost parameter, must be larger than 1 and be a power of 2.r
: Block size parameter.p
: Parallelization parameter.As mentioned in the documentation, n
, r
, and p
can adjust the computational and memory cost of the Scrypt algorithm. RFC 7914 recommends values of r=8
, p=1
, where the original Scrypt paper suggests that n
should have a minimum value of 2**14
for interactive logins or 2**20
for more sensitive files; you can check the documentation for more information.
Next, we make a function to load a previously generated salt:
Now that we have the salt generation and key derivation functions, let's make the core function that generates the key from a password:
The above function accepts the following arguments:
password
: The password string to generate the key from.salt_size
: An integer indicating the size of the salt to generate.load_existing_salt
: A boolean indicating whether we load a previously generated salt.save_salt
: A boolean to indicate whether we save the generated salt.After we load or generate a new salt, we derive the key from the password using our derive_key()
function, and finally, return the key as a Base64-encoded text.
Now we can use the same encrypt()
function we defined earlier:
For the decrypt()
function, we add a simple try-except block to handle the exception when the password is wrong:
Awesome! Let's use argparse
so we can pass arguments from the command line:
Let's test our script by encrypting data.csv
as previously:
You'll be prompted to enter a password, get_pass()
hides the characters you type, so it's more secure. You'll also notice that the salt.salt
file is generated.
If you open the target data.csv
file, you'll see it's encrypted. Now, let's try to decrypt it with the wrong password:
The data.csv
remains as is. Let's pass the correct password that was used in the encryption:
Amazing! You'll see that the data.csv
returned to its original form.
Note that if you generate another salt (by passing -s
or --salt-size
) while decrypting, even if it's the correct password, you won't be able to recover the file as a new salt will be generated that overrides the previous one, so make sure not to pass -s
or --salt-size
when decrypting.
Check cryptography's official documentation for further details and instructions.
Note that 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 using some methods of splitting the data or file compression for large files!
Here is the full code for both techniques used in this tutorial.
You can build a ransomware using this code. You can also check our Ethical Hacking with Python EBook to build that and other 36 hacking tools!
READ ALSO: How to Download All Images from a Web Page in Python.
Happy Coding ♥
Just finished the article? Now, boost your next project with our Python Code Generator. Discover a faster, smarter way to code.
View Full Code Auto-Generate My Code
Got a coding query or need some guidance before you comment? Check out this Python Code Assistant for expert advice and handy tips. It's like having a coding tutor right in your fingertips!