Flask server for storing encrypted images
View Demo ยท Documentation ยท Report Bug ยท Request Feature
- About the Project
- Getting Started
- Usage
- REST API Documentation
- RSA Encryption Algorithm
- Roadmap
- Contributing
- FAQ
- License
- Contact
- Acknowledgements
Client
Server
Database
- Register and login user.
- Storing image: app client encrypts the image with the RSA algorithm and sends
the request to the server to store the image.
- Image encrypted is required to be openable, but the opener may or may not understand the image.
- View the image list.
- Download image: client download encrypted images and decrypts it using the
user's RSA private key.
- Download one image.
- Download all images.
- Share the image with others: other users can download the image.
- After registration, an account is created with this information:
- username.
- ID.
- RSA public key (provided by the user before registration).
- Server connects with the client by using REST API.
To run this project, you will need to add the following environment variables to
your .env
file:
-
App configs:
SECRET_KEY
: Secret key for Flask application.UPLOADED_IMAGES_DEST
: Destination folder for server downloading uploaded images. Default:src/assets
.Note: The application will automatically create a new
UPLOADED_IMAGE_DEST
directory if it does not exist andDOWNLOAD_UPLOADED_IMAGES
isTrue
.FLASK_ENV
: Enable hot reloading indevelopment
mode. Default:production
.Note: Change to "development" mode to enable hot reloading.
DOWNLOAD_UPLOADED_IMAGES
: Enable server downloading uploaded images. Default:False
. -
JWT configs:
JWT_ACCESS_TOKEN_EXPIRES
: Time in seconds for access token expiration. Default:3600
(1 hour).JWT_SECRET_KEY
: Secret key for JWT. -
MongoDB configs:
MONGODB_HOST
: An URI to connect to your database
E.g:
# .env
# App configs
SECRET_KEY="my secret key"
UPLOADED_IMAGES_DEST="src/assets"
# Change to "development" to enable hot reloading
FLASK_ENV="production"
DOWNLOAD_UPLOADED_IMAGES=False
# JWT configs
JWT_ACCESS_TOKEN_EXPIRES=3600 # 1 hour
JWT_SECRET_KEY="my super secret key"
# MongoDB configs
# HOST not URI
MONGODB_HOST="mongodb+srv://{username}:{password}@crypto-image.u1r0p.mongodb.net/test"
You can also check out the file .env.example
to see all required environment
variables.
-
Python:
>= 3.9
. -
This project uses Poetry as package manager:
Linux, macOS, Windows (WSL)
curl -sSL https://install.python-poetry.org | python3 -
Read more about installation on Poetry documentation.
Clone the project:
git clone https://github.com/DuckyMomo20012/image-n-crypt.git
Go to the project directory:
cd image-n-crypt
Install dependencies:
poetry install
OR:
Export Poetry dependencies to file requirements.txt
:
poetry export -f requirements.txt --output requirements.txt
Note: You can add option:
--dev
to include development dependencies.
Then install dependencies with pip
:
pip install -r requirements.txt
Activate the virtual environment:
poetry shell
Start the program:
poe dev
OR
flask run
Access local Swagger documentation:
-
Test REST API endpoints: You can test endpoints using these ways:
-
Hoppscoth: an open-source API development ecosystem
- You can import pre-defined REST API endpoints from the file
data/hoppscoth.json
to Hoppscotch.
- You can import pre-defined REST API endpoints from the file
-
Local Swagger documentation: a Swagger UI is generated from REST API endpoints using Flask-RESTX.
- You can access this documentation: http://127.0.0.1:5000/api/v1/
-
File
client/api.py
: pre-defined functions to send requests to the server. -
Client console: poorly crafted client.
- You can run this client using the file
client/main.py
.
Note: But you can use this client to decrypt downloaded images!
- You can run this client using the file
-
-
Sample data:
-
You can import sample data from folder
data
to your database. -
Test data will have these sample users:
Sample users
admin: password: admin private key: rsa_admin.txt admin2: password: admin private key: rsa_admin2.txt admin2: password: admin private key: rsa_admin3.txt
-
To deploy this project on Heroku
Config deployment from scratch
Requirement files:
-
Procfile: Procfile specifies the commands that are executed by the app on startup:
E.g:
web: gunicorn app:app
Note: "web" for a web process type.
Note: first "app" refers to file
app.py
and second "app" refers toapp = Flask(__name__)
in fileapp.py
. Ref. -
requirements.txt: You can use Poetry to generate this file:
poetry export -f requirements.txt --output requirements.txt
Note: You have to install
gunicorn
dependency in yourrequirements.txt
. -
app.json: This file is required for deploying on Heroku using deploy button.
Read more in this tutorial: Deploying a Flask Application to Heroku
To register an account, you need to generate RSA key pair. You have to use the
function generateAndWriteKeyToFile
in src.helpers.crypto.crypto.py
to
generate key pair. This function will create two files:
rsa.txt
: RSA private key (This file must be kept secretly).rsa_pub.txt
: RSA public key.
OR:
- Using
register
fromclient/api.py
. - Using client console.
Then you can log in using your newly created account.
After login, you will receive an access_token
.
Note: Access token will be expired after 1 hour.
You have to use your access_token
to access protected endpoints.
-
Hoppscotch:
You have to paste your access token in the
Authorization
tab for each request. E.g:Note: You have to choose Authorization Type:
Bearer
-
Swagger doc: you MUST add your access token to access protected endpoints. By clicking the
Authorize
button:OR:
Clicking the lock icon (:lock:) on protected endpoints.
Then type your access token in the input field. E.g:
Bearer eyJ0eXAiO...
Note: Must be in the format
Bearer {access_token}
. -
File
client/api.py
:You have to call both functions
login
andgetUserInformation
:Example code
login(username="admin", password="admin") getUserInformation() # This will set global access_token and others global variables
-
All functions ALWAYS return a tuple[message, status code]
(tuple[str, int])
. -
This file contains some global variables, so you have to call both functions
login
andgetUserInformation
to set these global variables before calling other functions. -
To handle this response, you can use the function
handleRes
inclient/helpers.py
(This function is used by the client console too).
You can use functions from the file src/helpers/crypto/crypto.py
.
Examples below are extracted from file client/api.py
:
Generate RSA key pair
def register(username, password)
# ...
e, d, n = generateAndWriteKeyToFile("", writeFile=True)
Encrypt file
def uploadImage(fileName)
# ...
encrypt(
fileName,
n=n,
e=e,
imgEncryptedSaveDst=fileName_encrypt,
quotientSaveDst="quotient.txt",
)
Decrypt file
def downloadImage(downloadFile, privateKeyPath)
# ...
decrypt(
imgEncryptedPath=downloadFile,
privateKeyPath=privateKeyPath,
imgDecryptedSaveDst=downloadFile_d,
)
-
Currently, you can only upload images in PNG format.
-
Image should have a small size.
You can use local Swagger documentation to see details about endpoints.
OR:
See it on Wiki, REST API endpoints page, with details about implementation and explanation.
This section has moved to Wiki, RSA encryption algorithm page.
- Important: Remove entirely CSRF protection.
Keeps CSRF for Authentication. - Set the expiration time for the token.
- Add validator for only .PNG image file.
- Handle expired token error.
- Support more image extensions, and more file types.
- Client support decrypt image service.
- Handle file permissions (read/write).
Contributions are always welcome!
Please read the Code of Conduct.
-
Is this project still maintained?
- Yes, but we will only update UI, docs, or dependencies. New features won't be added frequently.
-
Is this project ready for production?
- No, this is a small project for practicing cryptographic systems or schemes. This wasn't meant for production.
- RSA algorithm is implemented from scratch, which is unsafe for production.
-
Client console error:
ModuleNotFoundError: No module named 'src'
:-
You are not exporting the
PYTHONPATH
environment variable to the project directory. -
Run this command:
-
Windows:
set PYTHONPATH=%cd%
-
Linux:
export PYTHONPATH=$(pwd)
-
-
-
Decrypt image took too long:
- Because we implement the RSA algorithm from scratch, so it is unsafe and has slow performance. You should upload an image with a smaller size.
-
Deploy on Heroku error:
No web processes running
:- You are missing file
Procfile
orgunicorn
dependency.
- You are missing file
Distributed under MIT license. See LICENSE for more information.
Duong Vinh - @duckymomo20012 - tienvinh.duong4@gmail.com
Project Link: https://github.com/DuckyMomo20012/image-n-crypt.
Here are useful resources and libraries that we have used in our projects:
- Flask: A lightweight WSGI web application framework.
- Flask-RESTX: A Flask extension that provides a consistent, simple, and powerful API framework.
- Flask-JWT-Extended: Adds support for using JSON Web Tokens (JWT) to Flask for protecting routes.
- Awesome Readme Template: A detailed template to bootstrap your README file quickly.