Last active
July 24, 2021 13:30
-
-
Save djui/a945426b7f3c0bd45e3b to your computer and use it in GitHub Desktop.
Simple TOTP implementation in Python as CLI
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 python | |
from __future__ import print_function | |
import base64 | |
import hashlib | |
import hmac | |
import struct | |
import sys | |
import time | |
class TOTP(): | |
class TOTPException(Exception): | |
def __init__(self, msg): | |
self.msg = msg | |
def __str__(self): | |
return repr(self.msg) | |
def __init__(self, secret): | |
if not secret: | |
raise TOTP.TOTPException('Invalid secret') | |
self.secret = secret | |
def generate(self): | |
try: | |
key = base64.b32decode(self.secret) | |
num = int(time.time()) // 30 | |
msg = struct.pack('>Q', num) | |
# Take a SHA1 HMAC of key and binary-packed time value | |
digest = hmac.new(key, msg, hashlib.sha1).digest() | |
# Last 4 bits of the digest tells which 4 bytes to use | |
offset = ord(digest[19]) & 15 | |
token_base = digest[offset : offset+4] | |
# Unpack that into an integer and strip it down | |
token_val = struct.unpack('>I', token_base)[0] & 0x7fffffff | |
token_num = token_val % 1000000 | |
# Pad with leading zeroes | |
token = '{0:06d}'.format(token_num) | |
return token | |
except: | |
raise TOTP.TOTPException('Invalid secret') | |
def main(args): | |
if len(args): | |
token = sys.stdin.readline().strip() if args[0] == '-' else args[0] | |
elif not sys.stdin.isatty(): | |
token = sys.stdin.readline().strip() | |
else: | |
return 'Usage: totp <secret>' | |
try: | |
print(TOTP(token).generate()) | |
except TOTP.TOTPException as e: | |
return 'Error: ' + e.msg | |
if __name__ == '__main__': | |
try: | |
sys.exit(main(sys.argv[1:])) | |
except KeyboardInterrupt: | |
sys.exit(1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
look at https://github.com/susam/mintotp/blob/master/mintotp.py — even less lines