DEV Community

Muhammad Saim
Muhammad Saim

Posted on

Python Flask File CheckSum

Hello.! I hope you are doing great. Today we will learn how to make a small applictaion which will create checksum of file and evaluate the file with the checksum.

For the checksum I'll be using SHA256 you can use whatever hasing algo you want. You can find the code in this GitHub Repo.

Let's get started with the applictaion.

Make a new diretcory and step into it

mkdir flask-checksum && cd flask-checksum
Enter fullscreen mode Exit fullscreen mode

Initialize the virtualenvironment

python -m venv vnev
Enter fullscreen mode Exit fullscreen mode

OR

virtualenv venv
Enter fullscreen mode Exit fullscreen mode

Activate the virtualenv

source venv/bin/activate
Enter fullscreen mode Exit fullscreen mode

Now it time to install flask

pip install flask
Enter fullscreen mode Exit fullscreen mode

Now its time to create the diretcory structure for our applictaion I'll make it simple.

📦flask-checksum
 ┣ 📂static
 ┃ ┣ 📂css
 ┃ ┣ 📂js
 ┃ ┗ 📂uploads
 ┣ 📂templates
 ┃ ┣ 📂includes
 ┃ ┣ 📂layouts
 ┃ ┗ 📂pages
 ┗ 📜app.py
Enter fullscreen mode Exit fullscreen mode

Download and place CSS and Js files for this project in static/css and static/js respectively. After that your directory structure will look like this.

📦static
 ┣ 📂css
 ┃ ┗ 📜bootstrap.min.css
 ┣ 📂js
 ┃ ┗ 📜bootstrap.bundle.min.js
 ┗ 📂uploads
 ┃ ┗ 📜.gitignore
Enter fullscreen mode Exit fullscreen mode

Now open app.py start building our applictaion and these line of code this will show output of the hello, world in your browser.

from flask import Flask


app = Flask(__name__)

@app.route('/')
def index():
   return "Hello, World"


if __name__ == '__main__':
   app.run()
Enter fullscreen mode Exit fullscreen mode

Run this application.

python app.py
Enter fullscreen mode Exit fullscreen mode

This will start a server and you can access the application on this URL 127.0.0.1:5000.

Its time to create templates for our applictaion in templates/layouts create app.html file this will be our master layout of the applictaion all these templates will extend this template.

app.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}{% endblock %}</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}">
</head>
<body class="bg-white-500">

    {% include 'includes/navbar.html' %}

    <div class="container">
        {% block content %}{% endblock %}
    </div>

    <script src="{{ url_for('static', filename='js/bootstrap.bundle.min.js') }}"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Create a file navbar.html in templates/includes.

navbar.html

<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
  <div class="container">
    <a class="navbar-brand" href="{{ url_for('create_checksum') }}">File CheckSum</a>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ms-auto mb-2 mb-lg-0">
        <li class="nav-item">
          <a class="nav-link {% if request.endpoint == 'create_checksum' %} active {% endif %}" aria-current="page" href="{{ url_for('create_checksum') }}">Create</a>
        </li>
        <li class="nav-item">
          <a class="nav-link {% if request.endpoint == 'verify_checksum' %} active {% endif %}" href="{{ url_for('verify_checksum') }}">Verify</a>
        </li>
      </ul>
    </div>
  </div>
</nav>
Enter fullscreen mode Exit fullscreen mode

Now we need two more templates for our applictaion one for creating checksum and 2nd for verifing. Let's create two more files in templates/pages first will be create.html and 2nd will be verify.html.

create.html

{% extends 'layouts/app.html' %}

{% block title %} Create CheckSum {% endblock %}

{% block content %}

    <div class="row py-5">
        <div class="col-md-8 offset-md-2 col-sm-12">
            <div class="card shadow">
                <div class="card-body">
                    <h5 class="card-title">
                        Create CheckSum
                    </h5>
                    <form action="{{ url_for('create_checksum') }}" method="post" enctype="multipart/form-data">
                        <div class="mb-3">
                            <label for="formFile" class="form-label">File</label>
                            <input class="form-control" type="file" id="formFile" name="file">
                        </div>
                        <div class="mb-3 float-end">
                            <button class="btn btn-primary" type="submit">create</button>
                        </div>
                    </form>
                </div>
            </div>
            {% if checksum %}
            <div class="card shadow mt-3">
                <div class="card-body">
                    <h4 class="card-title">your CheckSum</h4>
                    <p class="bg-primary p-3 text-white">{{ checksum }}</p>
                </div>
            </div>
            {% endif %}
        </div>
    </div>

{% endblock %}
Enter fullscreen mode Exit fullscreen mode

verify.html

{% extends 'layouts/app.html' %}

{% block title %} Verify CheckSum {% endblock %}

{% block content %}

    <div class="row py-5">
        <div class="col-md-8 offset-md-2 col-sm-12">
            <div class="card shadow">
                <div class="card-body">
                    <h5 class="card-title">
                        Verify CheckSum
                    </h5>
                    <form action="{{ url_for('verify_checksum') }}" method="post" enctype="multipart/form-data">
                        <div class="mb-3">
                            <label for="formFile" class="form-label">File</label>
                            <input class="form-control" type="file" id="formFile" name="file">
                        </div>
                        <div class="mb-3">
                            <label for="checksum">CheckSum</label>
                            <input type="text" name="checksum" class="form-control" placeholder="CheckSum">
                        </div>
                        <div class="mb-3 float-end">
                            <button class="btn btn-primary" type="submit">Verify</button>
                        </div>
                    </form>
                </div>
            </div>
            {% if status != None %}
            <div class="card shadow mt-3">
                <div class="card-body">
                    {% if status %}
                        <div class="alert alert-success">Your file is authentic.</div>
                    {% else %}
                        <div class="alert alert-danger">Your file is not authentic.</div>
                    {% endif %}
                </div>
            </div>
            {% endif %}
        </div>
    </div>

{% endblock %}
Enter fullscreen mode Exit fullscreen mode

So after that your templates directory structure will look like this.

📦templates
 ┣ 📂includes
 ┃ ┗ 📜navbar.html
 ┣ 📂layouts
 ┃ ┗ 📜app.html
 ┗ 📂pages
 ┃ ┣ 📜create.html
 ┃ ┗ 📜verify.html
Enter fullscreen mode Exit fullscreen mode

Now create the main logic of our applictaion so we start with the creating checksum in app.py and this function in the file.

@app.route('/', methods=['GET', 'POST'])
def create_checksum():
    checksum = None
    if request.method == 'POST':
        file = request.files['file']
        new_name = secure_filename(file.filename)
        file.save('static/uploads/'+new_name)
        checksum = sha256(new_name)
        os.remove('static/uploads/'+new_name)
    return render_template('pages/create.html', checksum=checksum)
Enter fullscreen mode Exit fullscreen mode

After adding this function your app.py will look like this.

from flask import Flask, render_template, request
from werkzeug.utils import secure_filename
import hashlib
import os


app = Flask(__name__)


@app.route('/', methods=['GET', 'POST'])
def create_checksum():
    checksum = None
    if request.method == 'POST':
        file = request.files['file']
        new_name = secure_filename(file.filename)
        file.save('static/uploads/'+new_name)
        checksum = sha256(new_name)
        os.remove('static/uploads/'+new_name)
    return render_template('pages/create.html', checksum=checksum)



if __name__ == '__main__':
    app.run(debug=True)
Enter fullscreen mode Exit fullscreen mode

Now create our 2nd function for verifying the checksum.

@app.route('/verify-checksum', methods=['GET', 'POST'])
def verify_checksum():
    status = None
    if request.method == 'POST':
        file = request.files['file']
        checksum = request.form.get('checksum')
        new_name = secure_filename(file.filename)
        file.save('static/uploads/' + new_name)
        new_checksum = sha256(new_name)
        status = checksum == new_checksum
        os.remove('static/uploads/' + new_name)
    return render_template('pages/verify.html', status=status)
Enter fullscreen mode Exit fullscreen mode

After adding this function your app.py will look like this.

from flask import Flask, render_template, request
from werkzeug.utils import secure_filename
import hashlib
import os


app = Flask(__name__)


@app.route('/', methods=['GET', 'POST'])
def create_checksum():
    checksum = None
    if request.method == 'POST':
        file = request.files['file']
        new_name = secure_filename(file.filename)
        file.save('static/uploads/'+new_name)
        checksum = sha256(new_name)
        os.remove('static/uploads/'+new_name)
    return render_template('pages/create.html', checksum=checksum)


@app.route('/verify-checksum', methods=['GET', 'POST'])
def verify_checksum():
    status = None
    if request.method == 'POST':
        file = request.files['file']
        checksum = request.form.get('checksum')
        new_name = secure_filename(file.filename)
        file.save('static/uploads/' + new_name)
        new_checksum = sha256(new_name)
        status = checksum == new_checksum
        os.remove('static/uploads/' + new_name)
    return render_template('pages/verify.html', status=status)


if __name__ == '__main__':
    app.run(debug=True)
Enter fullscreen mode Exit fullscreen mode

Now its time for the main and important function of the application which will be the responsible for the hasing.

def sha256(file_name):
    hash_sha256 = hashlib.sha256()
    with open('static/uploads/'+file_name, "rb") as f:
        for chunk in iter(lambda: f.read(4096), b""):
            hash_sha256.update(chunk)
    return hash_sha256.hexdigest()
Enter fullscreen mode Exit fullscreen mode

After adding this function your app.py will look like this.

from flask import Flask, render_template, request
from werkzeug.utils import secure_filename
import hashlib
import os


app = Flask(__name__)


@app.route('/', methods=['GET', 'POST'])
def create_checksum():
    checksum = None
    if request.method == 'POST':
        file = request.files['file']
        new_name = secure_filename(file.filename)
        file.save('static/uploads/'+new_name)
        checksum = sha256(new_name)
        os.remove('static/uploads/'+new_name)
    return render_template('pages/create.html', checksum=checksum)


@app.route('/verify-checksum', methods=['GET', 'POST'])
def verify_checksum():
    status = None
    if request.method == 'POST':
        file = request.files['file']
        checksum = request.form.get('checksum')
        new_name = secure_filename(file.filename)
        file.save('static/uploads/' + new_name)
        new_checksum = sha256(new_name)
        status = checksum == new_checksum
        os.remove('static/uploads/' + new_name)
    return render_template('pages/verify.html', status=status)


def sha256(file_name):
    hash_sha256 = hashlib.sha256()
    with open('static/uploads/'+file_name, "rb") as f:
        for chunk in iter(lambda: f.read(4096), b""):
            hash_sha256.update(chunk)
    return hash_sha256.hexdigest()


if __name__ == '__main__':
    app.run(debug=True)
Enter fullscreen mode Exit fullscreen mode

Now its time to run the application

python app.py
Enter fullscreen mode Exit fullscreen mode
http://127.0.0.1:5000
Enter fullscreen mode Exit fullscreen mode

Image description

Thanks for being with me.

If you want to learn Flask I have started my series Flask For Beginners Please do check out.

What you guys think and query and suggestion you have to feel free to write it down.

Thanks 🤗

Top comments (0)