Sitemap

Two-factor Authentication OTP generation using Vanilla Python

7 min readMay 19, 2023

--

Press enter or click to view image in full size
Source: Hackanons

Introduction

Security is more vital than ever in today’s digital environment. With so much sensitive information being transacted online, it’s critical to take every precaution to prevent unauthorized access. One-Time Passwords (OTPs) are one of the most successful methods for accomplishing this. OTPs are one-time passwords that are only valid for one login session or transaction and cannot be replayed or reused. In this technical coding blog, we will look at how to construct OTPs with Python and incorporate them into your apps for further security.

In this article, I will be focusing on Time-Based One-Time Password (TOTP) which is one of the Multi-factor authentication (MFA) where a user is required to provide more than one verification factor to gain access to the account. TOTP is a two-factor authentication (2FA) that generates a unique, temporary passcode that is only valid for a short period set by the system. This authentication is immensely used in enterprise applications, gaming, cloud services, banking, and social media among others.

Step-by-step outline

  1. Tools required.
  2. Creating a TOTP Sequence Diagram.
  3. Installing necessary packages.
  4. Creating a directory and files.
  5. Creating a virtual environment.
  6. Otp generator code.

1. Tools Required

  • Code editor e.g. Visual Studio code (VS code), Pycharm.

2. Creating a TOTP Sequence Diagram

What is a sequence diagram and why do we need it? It is an interaction diagram that shows how processes operate with one another and in what order it will help us understand the requirements of the TOTP program we are going to create.

We will be using Mermaid to come up with one. If you are not familiar with it you can check it here. Create an otp_sdiagram.mmd file and write the code below to come up with a diagram.

sequenceDiagram
actor User
App UI ->>+ User: Prompt for Phone No.
User->>+App UI:Enters Phone No.
App UI->>-OTP Server:Sends phone no for OTP
participant OTP Server
Note right of OTP Server: Generates otp valid for 300s
OTP Server->>+SMS Client: Sends 6 digit code and phone no.
SMS Client-->>-User: SMS with 6 digits code
User->>+App UI: Enter code
App UI->>-OTP Server:Otp code verification
alt otp is Valid
OTP Server-->>+App UI: Success
App UI ->>+ User: Verified.
else otp is Invalid
OTP Server-->>+App UI: Failure
App UI ->>- User: Incorrect OTP
end

The diagram Preview will be like below

Press enter or click to view image in full size
OTP sequence diagram

This indicates that the application’s user interface will prompt the user to enter their phone number. When the user submits, the OTP server generates a 6-digit password that is only valid for 300 seconds and sends it to the user’s phone as an SMS. The user will then be required to enter the passcode to the app UI for verification; if the OTP is valid, the user will be granted access to the account; if it is invalid, the user will be alerted to try again.

3. Installing necessary packages

Given that we are using Vanilla Python. If you do not have Python installed or need a newer version you can go to Python's official site here and follow the instruction on installation.

4. Creating a directory and files.

Open the terminal and navigate to where you want to create the project files and execute the following commands one-by-one

$ mkdir TOTP_generator
$ cd TOTP_generator
$ touch otp.py

The first command creates a directory by the name TOTP_generator, the second command enables you to navigate into the directory and the third one creates a Python file we are going to use for the OTP generator code.

5. Creating a virtual environment

Before we start coding, we need to create a virtual environment for our project, this will help us manage and isolate the project dependencies and enables us to install specific versions of Python packages without affecting the system-wide Python installation or conflicting with other project.

Navigate to the TOTP_generator directory and run the following command to create a virtual environment

$ python3 -m venv otp_env
$ source otp_env/bin/activate

The first command creates the virtual environment (otp_env) and the second activates the environment.

Get Cosmas Bett Mandelah’s stories in your inbox

Join Medium for free to get updates from this writer.

How will you know that the virtual environment is activated successfully? From your terminal, it should look like below.

Press enter or click to view image in full size
Activating virtual environment

If the virtual environment is activated we are good to go.

6. Otp generator code

Open the otp.py file in your code editor e.g Vs code or Pycharm

We start by importing the required module to enable us to get our project running. Below is a list and their significance in this program

  • time: It will provide functions to work with time-related operations.
  • hmac: It implements the HMAC (Hash-based Message Authentication Code) algorithm for secure hashing.
  • hashlib: It provides hashing algorithms, such as SHA-1, for data integrity.
  • struct: It provides functions to work with time-related operations.
Press enter or click to view image in full size
Importing Modules

The next step is to generate a random secret key as a byte string.

secret = b'MysecretKey'

To be able to get generate the same OTP within a certain interval of time say for 5 mins, time steps of 300 seconds should be set and Unix time determined

time_step=300
current_time =int(time.time())

The time steps need to be converted into a byte string in big-endian format. However, before that, time steps should be calculated. This is done by dividing the current time by the time step value, as shown below.

time_steps = int(current_time / time_step)

# Pack the time steps as a big-endian byte string
time_bytes = struct.pack('>Q', time_steps)

The next step is to calculate the HMAC-SHA1 hash of the time steps by using the hmac.new() function, it is called with the secret key, time steps byte string, and SHA-1 hashing algorithm to calculate the HMAC-SHA1 hash.

hash = hmac.new(secret, time_bytes, hashlib.sha1).digest()

Starting from the offset determined in the previous step, a 4-byte slice is extracted from the hash and converted into an integer. The struct.unpack() function is used to convert the 4-byte slice into an integer.

# Get the last 4 bits of the hash
offset = hash[-1] & 0x0F

otp_bytes = hash[offset:offset+4]

# Convert the bytes to an integer
otp_int = struct.unpack('>I', otp_bytes)[0]

Upto here the function produces a random integer and a 6-digit integer is needed for the random OTP code. Therefore, to obtain an integer from the previous step is modulo-divided by 10**6 to get a 6-digit number.

otp_raw = otp_int % 10**6

# This ensures that otp variable is 6-digits by formating the variable otp_raw as a 6-digit zero-padded string
otp = '{:06d}'.format(otp_raw)

# Displays Otp variable in your terminal when the code is executed
print('Your OTP is :',otp)

Let us run the code and see if we can get any output. Go to the terminal and run the below command to execute the code.

$ python3 otp.py

I have used VS code terminal for this case.

Press enter or click to view image in full size
Results from running the code.

OTP passcode is successfully generated, If you run the code in an interval of 5 minutes( the set time steps) it will generate the same OTP passcode.

Now we have the 6-digit OTP passcode we need to verify/validate. Validating means, generated OTP passcode is compared with the user’s input. If they match, the OTP is considered valid, and a corresponding message is printed. If the comparison fails, an exception is intentionally raised by trying to convert the string ‘abc’ to an integer, resulting in a ValueError. In this case, an "OTP is invalid" message is printed.

# Get the user's input for the OTP
user_otp = input('Enter your OTP:>>>>>> ')

# Verifying the OTP
if int(user_otp) == int(otp):
print('OTP is valid')
else:
try:
num = int('abc')
except ValueError:
print('OTP is invalid')

The results should be like below ;

Press enter or click to view image in full size
Verifying OTP passcode.

By implementing TOTPs and adopting robust security practices, organizations and individuals can significantly enhance the protection of their online accounts and sensitive data. Embracing these security measures is essential in today’s digital age to safeguard against evolving threats and maintain the trust and confidentiality of online transactions and communications.

You can obtain the complete code mentioned above from this source, repository.

--

--

Cosmas Bett Mandelah
Cosmas Bett Mandelah