From 72b7b3382571df4df0d0a7848d1d460a3327b86e Mon Sep 17 00:00:00 2001 From: Fredrik Wahlberg Date: Fri, 13 Jul 2018 11:27:48 +0200 Subject: [PATCH] Startar med en kodsnutt jag hittade --- README.md | 3 +++ totp.py | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 README.md create mode 100644 totp.py diff --git a/README.md b/README.md new file mode 100644 index 0000000..b45be2b --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +TOTP + +Tanken är att det ska bli ett cli-verktyg för att generera tokens från andOtps backupfiler \ No newline at end of file diff --git a/totp.py b/totp.py new file mode 100644 index 0000000..be07e3d --- /dev/null +++ b/totp.py @@ -0,0 +1,69 @@ +#!/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 ' + + 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)