diff --git a/mobilepasser/mobilepasser.py b/mobilepasser/mobilepasser.py index 76b2ae3..bba504e 100755 --- a/mobilepasser/mobilepasser.py +++ b/mobilepasser/mobilepasser.py @@ -1,14 +1,20 @@ #!/usr/bin/env python # coding=utf-8 +from __future__ import print_function + import argparse import os import sys -import ConfigParser +try: + import configparser +except ImportError: + # Python 2 compatibility. + import ConfigParser as configparser -from utils.activation_code import InvalidActivationKey, MissingActivationKey -from utils.token_generation import generate_mobilepass_token +from .utils.activation_code import InvalidActivationKey, MissingActivationKey +from .utils.token_generation import generate_mobilepass_token CONFIG_FILE = os.path.expanduser("~/.mobilepasser.cfg") @@ -32,7 +38,7 @@ help='Automatically bump the index by 1 and save to config file.') args = parser.parse_args() -Config = ConfigParser.ConfigParser({ +Config = configparser.ConfigParser({ 'index': str(INDEX), 'policy': POLICY, 'otp_length': str(LENGTH), @@ -66,14 +72,14 @@ def main(): sys.exit(1) try: - print generate_mobilepass_token(key, int(index), policy, int(length)) + print(generate_mobilepass_token(key, int(index), policy, int(length))) except (InvalidActivationKey, MissingActivationKey) as e: sys.stderr.write(e.message + '\n') sys.exit(1) # Increment the index and save to config if the auto_update_index flag is set if update: - Config.set('MobilePASS', 'index', int(index) + 1) + Config.set('MobilePASS', 'index', str(int(index) + 1)) cfgfile = open(args.config_file, 'w') Config.write(cfgfile) cfgfile.close() diff --git a/mobilepasser/utils/activation_code.py b/mobilepasser/utils/activation_code.py index 66bd2ce..2a290c5 100644 --- a/mobilepasser/utils/activation_code.py +++ b/mobilepasser/utils/activation_code.py @@ -1,8 +1,10 @@ import hashlib -import base32 -import base32_checksum -from activation_payload_v1 import ActivationPayloadV1 +import six + +from mobilepasser.utils import base32 +from mobilepasser.utils import base32_checksum +from mobilepasser.utils.activation_payload_v1 import ActivationPayloadV1 class InvalidActivationKey(Exception): @@ -78,8 +80,7 @@ def computeErrorCode(self, value): hash = hashlib.new('sha256') hash.update(value.tobytes()) - digest = hash.digest() - return ord(digest[-1]) + return six.indexbytes(hash.digest(),-1) def getEntropy(self): if self.legacy: diff --git a/mobilepasser/utils/base32_checksum.py b/mobilepasser/utils/base32_checksum.py index 1a87c1f..ec0dc12 100644 --- a/mobilepasser/utils/base32_checksum.py +++ b/mobilepasser/utils/base32_checksum.py @@ -1,4 +1,4 @@ -import base32 +from mobilepasser.utils import base32 def validateAndNormalize(encoded_string): if len(encoded_string.strip()) == 0: @@ -29,4 +29,4 @@ def validateAndNormalize(encoded_string): normalized_string += character checksum += ordinal_value * (1 + index % 5) - return normalized_string \ No newline at end of file + return normalized_string diff --git a/mobilepasser/utils/token_generation.py b/mobilepasser/utils/token_generation.py index b533ba8..e1a640a 100644 --- a/mobilepasser/utils/token_generation.py +++ b/mobilepasser/utils/token_generation.py @@ -6,7 +6,9 @@ import hmac import sys -from activation_code import ActivationCode +import six + +from mobilepasser.utils.activation_code import ActivationCode # I ported the KDF1 algorithm from the bouncycastle library that shipped with # the app as the python libraries that included this function seemed to be @@ -32,10 +34,10 @@ def KDF1(hash, secret, iv, start_position, key_length): #key should be passed by # only preserves the last byte. So it needed to do some bit math to preserve the whole # counter. This is what we're trying to replicate here. # See: http://stackoverflow.com/questions/2458495/how-are-integers-casted-to-bytes-in-java - hash.update(bytes(chr((counter >> 24) & 0xff))) - hash.update(bytes(chr((counter >> 16) & 0xff))) - hash.update(bytes(chr((counter >> 8) & 0xff))) - hash.update(bytes(chr(counter & 0xff))) + hash.update(six.int2byte((counter >> 24) & 0xff)) + hash.update(six.int2byte((counter >> 16) & 0xff)) + hash.update(six.int2byte((counter >> 8) & 0xff)) + hash.update(six.int2byte(counter & 0xff)) if iv != "": hash.update(iv) @@ -74,7 +76,7 @@ def long_to_byte_array(long_num): return byte_array def truncated_value(h): - bytes = bytearray(h.decode("hex")) + bytes = bytearray(h) offset = bytes[-1] & 0xf v = (bytes[offset] & 0x7f) << 24 | (bytes[offset+1] & 0xff) << 16 | \ (bytes[offset+2] & 0xff) << 8 | (bytes[offset+3] & 0xff) @@ -95,7 +97,7 @@ def generate_mobilepass_token(activation_key, index, policy='', length=6): entropy = code.getEntropy().tobytes() key = get_key(entropy, policy) - h = hmac.new(key, message, hashlib.sha256).hexdigest() + h = hmac.new(key, message, hashlib.sha256).digest() h = truncated_value(h) h = h % (10**length) return '%0*d' % (length, h) diff --git a/requirements.txt b/requirements.txt index 6c747d4..9c558e3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -bitstring==3.1.4 +. diff --git a/setup.py b/setup.py index e35c8d7..90dbd85 100644 --- a/setup.py +++ b/setup.py @@ -1,24 +1,14 @@ from setuptools import setup, find_packages -try: - from pip._internal.download import PipSession -except ImportError: - from pip.download import PipSession -try: - from pip._internal.req import parse_requirements -except ImportError: - from pip.req import parse_requirements - -def reqs(path): - return [str(r.req) for r in parse_requirements(path, session=PipSession())] - -INSTALL_REQUIRES = reqs("requirements.txt") setup( name='MobilePASSER', version='1.0', description='A reimplementation of the MobilePASS client in Python.', packages=find_packages(), - install_requires=INSTALL_REQUIRES, + install_requires=[ + "bitstring~=3.1.4", + "six" + ], entry_points={ 'console_scripts': ['mobilepasser = mobilepasser.mobilepasser:main',] },