1
0
mirror of https://github.com/gryf/softtoken.git synced 2025-12-21 05:17:59 +01:00

Initial commit

This commit is contained in:
Daniel Alvarez
2016-11-03 19:32:04 +01:00
commit b2e13b6594
10 changed files with 662 additions and 0 deletions

164
softtoken/softtoken.py Normal file
View File

@@ -0,0 +1,164 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from __future__ import print_function
import argparse
import base64
import configparser
import hashlib
from os import path
from os import urandom
import sys
from pykeyboard import PyKeyboard
import pyotp
__version__ = '0.0.1'
CONFIG_FILE = 'softtoken.conf'
def load_config():
dir_path = path.join(
path.dirname(path.realpath(__file__)),
CONFIG_FILE)
cfg = configparser.SafeConfigParser()
cfg.read(dir_path)
return cfg
def save_config(cfg):
dir_path = path.join(
path.dirname(path.realpath(__file__)),
CONFIG_FILE)
try:
with open(dir_path, 'w+') as configfile:
cfg.write(configfile)
except Exception:
print('ERROR: Cannot write config file')
sys.exit(2)
def create_token(name, hash_function='sha256', digits=6, seed_length=20):
cfg = load_config()
if cfg.has_section(name):
print('Token %s already exists. Delete it first' % name)
sys.exit(2)
seed = urandom(seed_length)
cfg.add_section(name)
cfg.set(name, 'hash', hash_function)
cfg.set(name, 'digits', str(digits))
cfg.set(name, 'seed', base64.b32encode(seed))
save_config(cfg)
print('\nNew Token created:\n\n%s\n-------------' % name)
print('Seed (hex): %s' % seed.encode('hex'))
print('Seed (b32): %s\n' % base64.b32encode(seed))
def delete_token(name):
cfg = load_config()
if not cfg.has_section(name):
print('Token %s does not exist' % name)
sys.exit(2)
cfg.remove_section(name)
save_config(cfg)
print("Token %s successfully deleted" % name)
def print_tokens():
cfg = load_config()
for section in cfg.sections():
print("[*] %s" % section)
def main():
parser = argparse.ArgumentParser(version=__version__)
parser.add_argument('--new', action='store_true', default=False,
dest='new_token', help='Generate a new Soft Token')
parser.add_argument('--delete', action='store_true', default=False,
dest='delete_token', help='Delete a Soft Token')
parser.add_argument('--list', action='store_true', default=False,
dest='list_tokens', help='List configured tokens')
parser.add_argument('--token', '-t', required=False, dest='token_name',
help='Soft Token name')
parser.add_argument('--hash', default='sha256', dest='hash_function',
choices=('sha1', 'sha256', 'sha512'), help='Hash '
'function to use (default is sha256)')
parser.add_argument('--digits', '-d', type=int, default=6, dest='digits',
help='OTP Length (default is 6)')
parser.add_argument('--length', '-l', type=int, default=20,
dest='seed_length', help='Seed length in bytes '
'(default is 20)')
parser.add_argument('-X', action='store_true', default=False,
dest='print_focus', help='Output the OTP where '
'the current focus is')
args = parser.parse_args()
if args.list_tokens:
print_tokens()
sys.exit(0)
if args.token_name is None:
print("A Token name is required for this action")
parser.print_help()
sys.exit(-1)
if args.new_token:
create_token(args.token_name,
args.hash_function,
args.digits,
args.seed_length)
sys.exit(0)
if args.delete_token:
delete_token(args.token_name)
sys.exit(0)
if args.list_tokens:
print_tokens()
sys.exit(0)
# Generate new OTP if the token exists
cfg = load_config()
if not cfg.has_section(args.token_name):
print('Token %s does not exist' % args.token_name)
sys.exit(2)
if args.hash_function == 'sha1':
hf = hashlib.sha256
elif args.hash_function == 'sha256':
hf = hashlib.sha256
elif args.hash_function == 'sha512':
hf = hashlib.sha512
seed = cfg.get(args.token_name, 'seed')
totp = pyotp.TOTP(seed, digest=hf, digits=args.digits)
otp = totp.now()
if args.print_focus:
k = PyKeyboard()
k.type_string(otp)
else:
print(otp)
if __name__ == "__main__":
main()