Generating Time-Based OTPs with Python and pyotp

When it comes to Two-factor authentication (2FA), One-time passwords (OTPs) play a critical role in enhancing security. Many applications, like Microsoft Authenticator, Google Authenticator, and DUO, use Time-based One-Time Password (TOTP) algorithms to generate OTPs that refresh every 30 seconds. In this post, I’ll walk you through how to generate a TOTP code in Python using the pyotp library, which mirrors how apps like Microsoft Authenticator work.

Understanding the TOTP Algorithm

TOTP combines a shared secret with the current time to generate a one-time password. Here’s how it works:

  1. The Secret Key: The core component in TOTP is a unique secret key. This key, often encoded in a QR code, is shared between the server and the client (e.g., your mobile app) during setup. In our example, this secret is provided as a command-line argument.
  2. Time-Based Calculation: TOTP uses the current time, divided into 30-second intervals (by default), along with the secret to generate a new OTP for each interval. So, as long as the server and client time are in sync, the generated OTP will match.
  3. Cryptographic Hashing: TOTP uses the HMAC-SHA1 hash function on the secret and time values, then converts the result into a short numeric code.

The Script: Generating OTPs in Python

This script shows how simple it is to generate OTPs in Python using the pyotp library. Here’s the full code:

import sys
import pyotp

if len(sys.argv) > 1:
    key = sys.argv[1]
else:
    print("Usage: python3 otp.py <secret_key>")
    sys.exit(1)

print(pyotp.TOTP(key).now())

Let’s break down what each part does.

Code Explanation

1. Importing Required Libraries:

We use sys to handle command-line arguments, and pyotp (a Python library for OTP generation) to handle the TOTP calculation.

2. Receiving the Secret Key:

sys.argv takes the first command-line argument as the secret key. If the argument is missing, it prompts for the correct usage and exits.

3. Generating the OTP:

pyotp.TOTP(key).now() generates the OTP by passing the secret key into TOTP(). The now() method then calculates the OTP for the current 30-second time slice.

Running the Script

To use the script, run the following command in your terminal:

python3 otp.py <secret_key>

Replace <secret_key> with your own secret. The output will be a one-time password that matches what’s generated by authenticator apps using the same secret.

How This Relates to QR Code Authentication

When setting up 2FA, apps like Microsoft Authenticator scan a QR code containing a URL with the secret embedded in it. This QR code might look like:

otpauth://totp/YourService:your.email@example.com?secret=JBSWY3DPEHXXXXXX&issuer=YourService

The secret parameter is what we use in the script. Once scanned, your authenticator app stores the secret and uses it, alongside the current time, to produce matching OTPs every 30 seconds.

I scanned a TOTP QR code from a website to retrieve my secret key. Using this Python script, I generated a TOTP code and compared it with the code from my Microsoft Authenticator app—they matched perfectly.

Conclusion

Generating your own OTPs with Python is straightforward and provides insight into how TOTP-based 2FA apps work behind the scenes. By combining a secret with the current time, TOTP provides a secure, time-sensitive code that keeps your accounts safe. Try experimenting with different secrets, and you’ll see that each one consistently produces a unique OTP at any given moment.

For more details, check out pyotp on GitHub to dive deeper into OTP generation.