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])

128
totp.py Normal file → Executable file
View File

@@ -1,14 +1,93 @@
#!/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 sys
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):
@@ -48,22 +127,33 @@ class TOTP():
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)
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])