Image encryption and decryption web application using Flask

Vinayak Sharma
4 min readNov 18, 2020

A few months back I made a flask app during a hackathon. The web app helps in easy encryption and decryption of an image. It is based on the XOR operation. Upon encryption, the user is given back an encrypted image along with a key. Later on, the user can upload the encrypted image back to the web app along with the key, and in return, the user is given back a decrypted image only if the key entered is correct. The link to my deployed website for this project image security

The Tech stack used for making this app is Flask + Jinja framework. The sole function of this web app is image encryption and decryption.

The reason for choosing flask is because it is relatively easy to fetch or provide images in Flask. The other reason for using Flask is python (easy operations).

Kindly refer to this documentation if you want to set up a flask project.

We require 2 main routes for all the operations in this web app.

Firstly I created the upload or the encryption route. The operation under this route consists of the user uploading an image and getting back an encrypted image along with a key.

@app.route('/encryption', methods = ['POST'])  
def encryption():
if request.method == 'POST':
global f
f = request.files['file']
f.save(f.filename)
key,image=encrypt(f.filename)
return render_template('encryption.html',
title='Encrypted',
year=datetime.now().year,
message='This is your encrypted image', name = f.filename,keys=key,images=image)

In the above route, we are requesting a ‘file’ and then saving it with the filename.

key,image=encrypt(f.filename)

This line of code is basically calling the encrypt function and passing the fileName (not the image itself) to it to get back the key along with the image.

The second important route is for decryption.

@app.route('/decyption', methods = ['POST'])  
def decyption():
if request.method == 'POST':
global f
f = request.files['file']
f.save(f.filename)
text = request.form['key']
key=int(text)
image=decrypt(key,f.filename)
return render_template('decyption.html',
title='Decrypted',
year=datetime.now().year,
message='This is your Decrypted image', name = f.filename)

In the above route, we again do the same process as we did in the encryption route. We first save the image file.

text = request.form['key']

This command fetches the key entered by the user so that we can, later on, use it when we decrypt the image uploaded by the user.

image=decrypt(key,f.filename)

In this command, we pass the key along with the filename to the decrypt function, and in return, we get back the decrypted image.

for returning an image file to the user we use the below command

@app.route('/return-file')
def return_file():
return send_file("../enc.jpg",attachment_filename="enc.jpg")

to read more about how to handle files in flask, kindly refer to this link

The next main thing required in this web application is the encrypt and the decrypt function itself.

def encrypt(file):
fo = open(file, "rb")
image=fo.read()
fo.close()
image=bytearray(image)
key=random.randint(0,256)
for index , value in enumerate(image):
image[index] = value^key
fo=open("enc.jpg","wb")
imageRes="enc.jpg"
fo.write(image)
fo.close()
return (key,imageRes)

In the above function, we are taking an argument named ‘file’. This argument is responsible for providing us with the image file uploaded by the user. We open the file using the open command and save it using the .read() command.

fo = open(file, "rb")
image=fo.read()
fo.close()

We convert this image to a byte array because the XOR operation will be performed on these bytes

image=bytearray(image)

for generating a random Key we use the .randint(0,256) command. The reason for limiting the generation of keys up to 256 is because the maximum value that can be used in an XOR operation is 256. There are multiple ways for making this Key more secure but let’s focus on the main functionality of this web app for now.

for index , value in enumerate(image):
image[index] = value^key

The above FOR loop runs over all the bytes of the image and performs XOR operation using the generated key. Finally, we store this image using the below command

fo.write(image)

The decrypt function is very much identical to the encrypt function

def decrypt(key,file):
fo = open(file, "rb")
image=fo.read()
fo.close()
image=bytearray(image)
for index , value in enumerate(image):
image[index] = value^key
fo=open("dec.jpg","wb")
imageRes="dec.jpg"
fo.write(image)
fo.close()
return imageRes

Same as the encrypt function we first read the uploaded encrypted image by the user and store it. Then we convert the image into a byte array to perform an XOR operation on all the bytes of the array.

for index , value in enumerate(image):
image[index] = value^key

After this, we simply return the decrypted image to the user

For building the frontend I used the jinja framework. Flask and jinja is an awesome combination for making a killer hackathon or a self project. Below is a snapshot of the home page of my app.

To learn more about how to deploy a flask app to Heroku you can refer to this guide.

Github repo of this project: https://github.com/vinayaksh42/Image-Security

--

--