Raderar ursprungliga totp.py och döper om alla.py till totp.py

This commit is contained in:
2018-07-14 12:16:33 +02:00
parent d55c292201
commit af80b53402
2 changed files with 109 additions and 178 deletions

159
alla.py
View File

@@ -1,159 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
import argparse
import base64
import ConfigParser
import hashlib
import hmac
import json
import os
import struct
import time
def die(reason):
# Terminate with an error message
print("Ecountered an error, terminating")
print("Error message -", reason)
exit(1)
def get_arguments():
# Get input from the command line
parser = argparse.ArgumentParser()
parser.add_argument("site", nargs="*")
default_cfg_path = os.environ['HOME'] + '/.totprc'
parser.add_argument("-c", "--config", default=default_cfg_path, help='Path to config-file. Defaults to ~/.totprc')
args = parser.parse_args()
return args
def menu(data):
# Print a pretty menu to choose from
keynum = 1
print(" ---------------- Available keys ----------------")
print(" |")
for p in data:
print(" | %2d - %s" % (keynum, p["label"]))
keynum = keynum + 1
print(" |")
print(" ------------------------------------------------")
print(" | Please select which key to generate [1 - %d] |" % keynum)
print(" ------------------------------------------------")
print()
return keynum
def print_OTP(secret):
# Generate the key and pretty print it
value = TOTP(secret).generate()
# Format response like XXX XXX
print(value[:3], value[3:])
def read_config(args):
# Read from the config file
config = ConfigParser.ConfigParser()
try:
config.read(args.config)
except:
# Error in config file
die("Could not read %s" % args.config)
# Verify that the config is correct
try:
config.get('totp', 'andOTPfile')
except:
die("Could not find path to 'andOTPfile' in %s" % args.config)
if not os.path.isfile(config.get('totp', 'andOTPfile')):
die("The file %s does not exist" % config.get('totp', 'andOTPfile'))
return config
def read_file(config):
# Open and parse the data file
try:
with open(config.get('totp', 'andOTPfile')) as filen:
data = json.load(filen)
except:
die("Error parsing JSON, corrupt andOTP-file?")
return data
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')
if __name__ == '__main__':
args = get_arguments() # Get args from cmdline
cfg = read_config(args) # Read from the cfg file
data = read_file(cfg) # Open the data file
if not args.site: # Show a menu if no input
while True:
menu(data)
site = raw_input("Key #: ")
try:
site = int(site)
except:
print("Enter a number, not text.")
if site > len(data):
raw_input("Incorrect menu choice, press Enter to try again")
else:
print_OTP(data[site-1]["secret"]) # -1 since index start with 0 and the menu with 1
exit(0)
for p in data: # Try to find a matching site
if p["label"].strip().lower() == args.site[0].lower():
print_OTP(p["secret"])
exit(0)
die("Could not find '%s' in the andOTP file" % args.site[0])

126
totp.py Normal file → Executable file
View File

@@ -1,14 +1,93 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function from __future__ import print_function
import argparse
import base64 import base64
import ConfigParser
import hashlib import hashlib
import hmac import hmac
import json
import os
import struct import struct
import sys
import time import time
def die(reason):
# Terminate with an error message
print("Ecountered an error, terminating")
print("Error message -", reason)
exit(1)
def get_arguments():
# Get input from the command line
parser = argparse.ArgumentParser()
parser.add_argument("site", nargs="*")
default_cfg_path = os.environ['HOME'] + '/.totprc'
parser.add_argument("-c", "--config", default=default_cfg_path, help='Path to config-file. Defaults to ~/.totprc')
args = parser.parse_args()
return args
def menu(data):
# Print a pretty menu to choose from
keynum = 1
print(" ---------------- Available keys ----------------")
print(" |")
for p in data:
print(" | %2d - %s" % (keynum, p["label"]))
keynum = keynum + 1
print(" |")
print(" ------------------------------------------------")
print(" | Please select which key to generate [1 - %d] |" % keynum)
print(" ------------------------------------------------")
print()
return keynum
def print_OTP(secret):
# Generate the key and pretty print it
value = TOTP(secret).generate()
# Format response like XXX XXX
print(value[:3], value[3:])
def read_config(args):
# Read from the config file
config = ConfigParser.ConfigParser()
try:
config.read(args.config)
except:
# Error in config file
die("Could not read %s" % args.config)
# Verify that the config is correct
try:
config.get('totp', 'andOTPfile')
except:
die("Could not find path to 'andOTPfile' in %s" % args.config)
if not os.path.isfile(config.get('totp', 'andOTPfile')):
die("The file %s does not exist" % config.get('totp', 'andOTPfile'))
return config
def read_file(config):
# Open and parse the data file
try:
with open(config.get('totp', 'andOTPfile')) as filen:
data = json.load(filen)
except:
die("Error parsing JSON, corrupt andOTP-file?")
return data
class TOTP(): class TOTP():
class TOTPException(Exception): class TOTPException(Exception):
def __init__(self, msg): def __init__(self, msg):
@@ -48,22 +127,33 @@ class TOTP():
raise TOTP.TOTPException('Invalid secret') 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__': if __name__ == '__main__':
args = get_arguments() # Get args from cmdline
cfg = read_config(args) # Read from the cfg file
data = read_file(cfg) # Open the data file
if not args.site: # Show a menu if no input
while True:
menu(data)
site = raw_input("Key #: ")
try: try:
sys.exit(main(sys.argv[1:])) site = int(site)
except KeyboardInterrupt: except:
sys.exit(1) print("Enter a number, not text.")
if site > len(data):
raw_input("Incorrect menu choice, press Enter to try again")
else:
print_OTP(data[site-1]["secret"]) # -1 since index start with 0 and the menu with 1
exit(0)
for p in data: # Try to find a matching site
if p["label"].strip().lower() == args.site[0].lower():
print_OTP(p["secret"])
exit(0)
die("Could not find '%s' in the andOTP file" % args.site[0])