Python Hash Password Save in Postgres

Introduction

In this article we learn how to use Python to hash a password and save it in Postgres via the hashlib function built into Python’s hashlib library and then use SQL to insert the hashed password into our PostgreSQL database. Here’s how we’ll do it:

  • What? What is the hashlib function and what is its syntax?
  • How? We’ll set up a Python environment to use the “Render_template” and “Request” functions to send the user to an HTML form and retrieve data from the user, respectively. Then we will hash the password and insert it into a table in our PostgreSQL database.

Prerequisites

  • Some experience with the basics of writing queries in Postgres, using PG’s free PGadmin tool or other database admin tool. And/or writing applications with languages like Python, Javascript, PHP, C#, Java, ASP.Net, VB.Net, Note.js, Ruby, etc. In this case, we are using Python.
  • Using simple SQL statements, including INSERT INTO.
  • Familiarity with HTML forms. If not, that’s ok, you will learn some here.
  • Optional but helpful: Tutorial on naming conventions explaining why we prefix our variables, column names, table names, etc. as you see us doing in this article. For example, naming “t_variablename” with the “t” you see at the beginning in order to delineate it as a “text” (string) object and “tbl_” before table names in order to clearly mark those objects as tables.

Before we get into using hashlib(), which is a function for hashing a password in Python using the protocol of your choose, let’s briefly go over the basics of how the “request” and “render_template” functions work, because they are often used in conjunction with password hashing. For example, you build an HTML form for the user to enter an email and password to add to the Postgres database, you receive that data they submitted, hash the password, and then insert it into a table.

The first function we will learn how to use is the “request” function. It is used to pull data that was submitted either by form “post” or by “get” (querystring).

Syntax of the REQUEST() function

variable = request.args.get(field name, default value) # querystring, which is form method = GET in HTML.
variable = request.form.get(field name, default value) # post, which is form method = POST in HTML forms.

Analysis

  • field name: This parameter determines the name of the field (how it was named in your querystring or form). For example, “t_email” or “t_name_user”.
  • default value: In case no data was sent for that field, this is the value your variable will receive. This is an easy way to prevent 404 errors. We often put an empty string here, like ” “.

Here are some examples of how the syntax above might look when used in a project. We’ll leave out “get” as it has no relevance to our current learning:

t_name_user = request.form.get("t_name_user", "")
t_password = request.form.get("t_password", "")

Analysis

  • t_stage: This line of Python code is like saying to the server, “Look at the URL, find the ‘?’, and after that symbol, look for ‘t_stage=’ and put the value that comes after that ‘=’ into a local variable we are naming t_stage.”
  • t_name_user: This line of code grabs the value the user put into the HTML field named “t_name_user” and places that value in the local Python text variable we called “t_name_user”.

PostgreSQL’s Render_Template() function displays an HTML page for the user, which can be filled with dynamic content we control with parameters in the function. Note: Please don’t confuse it with the redirect function, which sends the user away without waiting for a return.

Syntax: RENDER_TEMPLATE() function

return render_template("page_name.html", t_message = "some data")

We supply the RENDER_TEMPLATE function with this parameter:

  • t_message: The contents of “t_message” will be sent, along with the user, to page_name.html, an html template you create, that is set up to receive and use t_message. Note: instead of “message”, you can call your variable anything you want. You can even send more variables. Look for our article that goes into detail on this function.

Now back to the topic at hand…

What is a hash?

A Hash Value, otherwise known as a checksum, is a text (string type) value which is the result of calculation of a Hash Algorithm. The algorithm we’ll use here is called SHA3-512. A primary use of Hashing is to determine the Integrity of Data, which in this case is a password. The determination of integrity will come in another lesson where someone attempts to log in and we want to check a hash of what they typed with the hash we will – in this article – store in the database.

Note that the SHA3_512 hashing algorithm became available in Python 3.6. We recommend this level of encryption is more difficult to break than 256.

What does the HASHLIB function do and what’s the syntax?

Syntax of the HASHLIB() function

    t_hashed = hashlib.sha3_512(t_user_input.encode())
    t_password = t_hashed.hexdigest()

SOME NECESSARY PYTHON CODE

You will need to install and reference these Python flask libraries in order to use the request and render_template functions, as well as the database insert we will do:

from flask import Flask
from flask import render_template # to render our html page
from flask import request # to get user input from form
import hashlib # included with Python; no install needed
import psycopg2 # for database connection

Step 1: Build an HTML form that will be the “template” we call later

Below is some barebones HTML, really the minimum you will need. Later, you may want to make it more modular by referencing a header, css file, and footer, but for now, this will work on all web browsers. Call this page “register.html” and save it in a folder called “templates”:

<html>
    <head>
        <link rel="shortcut icon" href="favicon.ico">
        <title>Python Hash Password and Save in Postgres Template</title>
    </head>
<body>
<!-- The message below encapsulated in an "h1" tag is why we call this page a template -->
<!-- It is what makes this page "dynamic" because the server fills -->
<!-- in at the spot where you see {{t_message}} with data you sent when you used -->
<!-- the "render_template()" function. -->
<h1>{{t_message}}</h1>
<!-- div to contain form -->
<div>
    <!-- Set up form and the file to process user input -->
    <form id='frmTest' name='frmTest' action='' method='post' onsubmit='return true;'>

    <!-- input box for the user to enter their user name -->
    <!-- Notice our input has a 'name' (parameter of the HTML input type) of 't_name_user'. -->
    <!-- This is how our request function chooses which data to retrieve. -->
    <div class="form-row">
      User Name: <input type="text"  name="t_name_user">
    </div>

    <div class="form-row">
      Password: <input type="text"  name="t_password">
    </div>

    <!-- button for user to submit the form -->
    <div>
      <input type="submit" name="btn_submit_add_user" value='Join'>
    </div>

    <!-- Close the form -->
    </form>
<!-- Close the container div -->
</div>
<!-- Close the body of the HTML document -->
</body>
</html>

Analysis

  • : Div is a way of encapsulating content in HTML documents. Often times we use divs to assign styles to content via an inline “style” tag or with a “class” tag pointing to some predefined CSS.
  • For the rest, use the comments we liberally placed in the HTML above.

Build a test application: from HTML to Postgres

Let’s begin by using Python’s render_template() function to send the user to the HTML page we built above and then retrieve the data submitted by the user using the request() function.

@app.route("/register", methods=["POST","GET"])
def sign_in():
    return RENDER_TEMPLATE("register.html", t_message = "Register Here")
    t_name_user = REQUEST.form.get("t_name_user", "")
    t_password = REQUEST.form.get("t_password", "")

Now we’ll do the actual hashing of the user’s input.

    t_hashed = hashlib.sha3_512(t_password.encode())
    t_password = t_hashed.hexdigest()

Analysis

  • We begin with the value a user put into “t_password”, hash it with the hashlib function, using the sha3_512 algorithm, and store the resulting – hashed – value in a variable we called “t_hashed”. This looks like a long series of bytes.
  • Next step is where we use the hexdigest function to convert the sequence of bytes returned by hashlib() into hex data.

Now, since this article is not about inserting records into a Postgres database as much as it is about hashing passwords, we’ll skip in-depth analysis of the SQL but we will provide the full source code below.

Full Source Code in Python

from flask import Flask
from flask import render_template # to render our html page
from flask import request # to get user input from form
import hashlib # included with Python; no install needed
import psycopg2 # for database connection

app = Flask(__name__)
@app.route("/")

t_host = "PostgreSQL database host address" # either "localhost", a domain name, or an IP address.
t_port = "5432" # default postgres port
t_dbname = "database name"
t_user = "database user name"
t_pw = "password"
db_conn = psycopg2.connect(host=t_host, port=t_port, dbname=t_dbname, user=t_user, password=t_pw)
db_cursor = db_conn.cursor()

@app.route("/register", methods=["POST","GET"])
def sign_in():
    return render_template("register.html", t_message = "Register Here")
    t_name_user = request.form.get("t_name_user", "")
    t_password = request.form.get("t_password", "")

    # Check for user name field is empty
    if t_name_user == "":
        t_message = "Register - empty field: Please fill in your user name."
        # Send user back to the dynamic html page (template), with a message
        return render_template("register.html", t_message = t_message)

    if t_password == "":
        t_message = "Please fill in your password"
        return render_template("register.html", t_message = t_message)

    # Hash the password they entered into a encrypted hex string
    t_hashed = hashlib.sha256(t_password.encode())
    t_password = t_hashed.hexdigest()

    # We take the time to build our SQL query string so that
    #   (a) we can easily and quickly read it; and
    #   (b) we can easily and quickly edit or add/remote lines.
    #   The more complex the query, the greater the benefits of this approach.
    s = ""
    s += "INSERT INTO tbl_users "
    s += "("
    s += " t_name_user"
    s += ",t_password"
    s += ") VALUES ("
    s += " '" + t_name_user + "'"
    s += ",'" + t_password + "'"
    s += ")"
    # IMPORTANT: the format above allows for a user to try to insert
    #   potentially damaging code, commonly known as "SQL injection".
    #   In another article (link below) we will show how to
    #   prevent that by using stored procedures.

    # Here we catch and display any possible errors
    #   while TRYing to commit the SQL script.
    db_cursor.execute(s)
    try:
        db_conn.commit()
    except psycopg2.Error as e:
        t_message = "Database error: " + e + "/n SQL: " + s
        return render_template("register.html", t_message = t_message)
    db_cursor.close()

    # Catch and display any errors that occur
    #   while TRYing to commit the execute our SQL script.
    try:
        db_conn.commit()
    except psycopg2.Error as e:
        t_message = "Database error: " + e + "/n SQL: " + s
        return render_template("register.html", t_message = t_message)

    # Clean up
    db_cursor.close()

SAFETY TIP: Use Stored Procedures

Protect the integrity of your users’ data by learning about

Conclusion

In this tutorial we learned how to use the Python hash password function and save it in Postgres. We also used the Request and Render_template functions to get data posted by the user to register using an HTML form and “Post”. Next we hashed their password and inserted it – along with username – as a new row in our PostgreSQL database table. We built a simple application using Python, HTML, and PostgreSQL. Finally, we gave you all of the Python source code you need to study and copy into your own projects.

Pilot the ObjectRocket Platform Free!

Try Fully-Managed CockroachDB, Elasticsearch, MongoDB, PostgreSQL (Beta) or Redis.

Get Started

Keep in the know!

Subscribe to our emails and we’ll let you know what’s going on at ObjectRocket. We hate spam and make it easy to unsubscribe.