Skip to content

Latest commit

 

History

History
653 lines (443 loc) · 16.6 KB

README.md

File metadata and controls

653 lines (443 loc) · 16.6 KB

Image-N-crypt

Flask server for storing encrypted images

contributors last update forks stars open issues license


📔 Table of Contents

🌟 About the Project

📷 Screenshots

screenshot

👾 Tech Stack

Client
Server
Database
DevOps

🎯 Features

  • 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.

🔑 Environment Variables

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 and DOWNLOAD_UPLOADED_IMAGES is True.

    FLASK_ENV: Enable hot reloading in development 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.

🧰 Getting Started

‼️ Prerequisites

  • 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.

🏃 Run Locally

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:

http://127.0.0.1:5000/api/v1/

🧪 Running Tests

  • Test REST API endpoints: You can test endpoints using these ways:

    • Hoppscoth: an open-source API development ecosystem

      hoppscotch.io

      • You can import pre-defined REST API endpoints from the file data/hoppscoth.json to Hoppscotch.
    • Local Swagger documentation: a Swagger UI is generated from REST API endpoints using Flask-RESTX.

      swagger

    • 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!

  • 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
      

🚩 Deployment

To deploy this project on Heroku

Deploy

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 to app = Flask(__name__) in file app.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 your requirements.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

👀 Usage

🙋 Register an account

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 from client/api.py.
  • Using client console.

Then you can log in using your newly created account.

After login, you will receive an access_token.

Screenshot

login response

Note: Access token will be expired after 1 hour.

🚷 Access protected endpoints

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:

    Screenshot

    hoppscotch token example

    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:

    Screenshot

    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 and getUserInformation:

    Example code
    login(username="admin", password="admin")
    getUserInformation() # This will set global access_token and others global
    variables

ℹ️ About file client/api.py:

  • 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 and getUserInformation to set these global variables before calling other functions.

  • To handle this response, you can use the function handleRes in client/helpers.py (This function is used by the client console too).

*️⃣ Encrypt and decrypt files manually:

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,
    )

📤 Upload image notes

  • Currently, you can only upload images in PNG format.

  • Image should have a small size.

📖 REST API Documentation

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.

🔮 RSA Encryption Algorithm:

This section has moved to Wiki, RSA encryption algorithm page.

🧭 Roadmap

  • 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).

👋 Contributing

Contributions are always welcome!

📜 Code of Conduct

Please read the Code of Conduct.

❔ FAQ

  • 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 or gunicorn dependency.

⚠️ License

Distributed under MIT license. See LICENSE for more information.

🤝 Contact

Duong Vinh - @duckymomo20012 - [email protected]

Project Link: https://github.com/DuckyMomo20012/image-n-crypt.

💎 Acknowledgements

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.