Simple script to generate a TOTP token. (source https://github.com/susam/mintotp). See https://tsumarios.github.io/blog/2022/10/07/how-totp-works/ for more.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import base64 | |
import datetime | |
import hmac | |
import os | |
import struct | |
import time | |
import sys | |
# This key should be kept hidden (e.g., in env variables, here supposed to be OTP_SHARED_KEY). The string here provided as default value is Base32 encoded and is just for the sake of demo. | |
KEY = os.environ.get('OTP_SHARED_KEY', 'ORZXK3LBOJUW643CNRXWO2LTMF3WK43PNVSQ====') | |
def hotp(key, counter, digits=6, digest='sha1'): | |
key = base64.b32decode(key.upper() + '=' * ((8 - len(key)) % 8)) | |
counter = struct.pack('>Q', counter) | |
mac = hmac.new(key, counter, digest).digest() | |
offset = mac[-1] & 0x0f | |
binary = struct.unpack('>L', mac[offset:offset+4])[0] & 0x7fffffff | |
return str(binary)[-digits:].zfill(digits) | |
def totp(key, time_step=30, digits=6, digest='sha1'): | |
return hotp(key, int(time.time() / time_step), digits, digest) | |
def main(): | |
while True: | |
# Generate a new OTP every second by using TOTP. | |
# NOTE: every 30s the OTP value will change :D | |
try: | |
secs = 30 - datetime.datetime.utcnow().second % 30 | |
otp_code = totp(KEY.strip()) | |
timer = '{:02d}s'.format(secs) | |
print(f"OTP: {otp_code} (expires in {timer})", end="\r") | |
time.sleep(1) | |
except KeyboardInterrupt: | |
print('', end="\r") | |
sys.exit(0) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment