From 82a042233f94230c99ecfdf0133e211e4966b777 Mon Sep 17 00:00:00 2001 From: Nick Bartos Date: Thu, 2 May 2019 11:43:58 +1000 Subject: [PATCH 1/3] Python 3 compatibility --- mobilepasser/mobilepasser.py | 14 +++++++++----- mobilepasser/utils/activation_code.py | 6 +++--- mobilepasser/utils/base32_checksum.py | 4 ++-- mobilepasser/utils/token_generation.py | 2 +- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/mobilepasser/mobilepasser.py b/mobilepasser/mobilepasser.py index 76b2ae3..d310265 100755 --- a/mobilepasser/mobilepasser.py +++ b/mobilepasser/mobilepasser.py @@ -5,10 +5,14 @@ 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 mobilepasser.utils.activation_code import InvalidActivationKey, MissingActivationKey +from mobilepasser.utils.token_generation import generate_mobilepass_token CONFIG_FILE = os.path.expanduser("~/.mobilepasser.cfg") @@ -32,7 +36,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,7 +70,7 @@ 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) diff --git a/mobilepasser/utils/activation_code.py b/mobilepasser/utils/activation_code.py index 66bd2ce..7c80dd6 100644 --- a/mobilepasser/utils/activation_code.py +++ b/mobilepasser/utils/activation_code.py @@ -1,8 +1,8 @@ import hashlib -import base32 -import base32_checksum -from activation_payload_v1 import ActivationPayloadV1 +from mobilepasser.utils import base32 +from mobilepasser.utils import base32_checksum +from mobilepasser.utils.activation_payload_v1 import ActivationPayloadV1 class InvalidActivationKey(Exception): 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..21dfa54 100644 --- a/mobilepasser/utils/token_generation.py +++ b/mobilepasser/utils/token_generation.py @@ -6,7 +6,7 @@ import hmac import sys -from activation_code import ActivationCode +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 From 35324ec80cd6e369d6eeca6b1a92f7723b86a3c4 Mon Sep 17 00:00:00 2001 From: Doug Tabacco Date: Wed, 12 Feb 2020 10:30:10 -0800 Subject: [PATCH 2/3] Update for Python 3.7 --- mobilepasser/mobilepasser.py | 2 +- mobilepasser/utils/activation_code.py | 3 +-- mobilepasser/utils/token_generation.py | 12 ++++++------ 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/mobilepasser/mobilepasser.py b/mobilepasser/mobilepasser.py index d310265..02a381a 100755 --- a/mobilepasser/mobilepasser.py +++ b/mobilepasser/mobilepasser.py @@ -77,7 +77,7 @@ def main(): # 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 7c80dd6..85e1b69 100644 --- a/mobilepasser/utils/activation_code.py +++ b/mobilepasser/utils/activation_code.py @@ -78,8 +78,7 @@ def computeErrorCode(self, value): hash = hashlib.new('sha256') hash.update(value.tobytes()) - digest = hash.digest() - return ord(digest[-1]) + return hash.digest()[-1] def getEntropy(self): if self.legacy: diff --git a/mobilepasser/utils/token_generation.py b/mobilepasser/utils/token_generation.py index 21dfa54..cb0e209 100644 --- a/mobilepasser/utils/token_generation.py +++ b/mobilepasser/utils/token_generation.py @@ -32,10 +32,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(bytes(chr((counter >> 24) & 0xff), encoding='utf8')) + hash.update(bytes(chr((counter >> 16) & 0xff), encoding='utf8')) + hash.update(bytes(chr((counter >> 8) & 0xff), encoding='utf8')) + hash.update(bytes(chr(counter & 0xff), encoding='utf8')) if iv != "": hash.update(iv) @@ -74,7 +74,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 +95,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) From b99fb33ec9ba5caff4d50568f0f2dfe508c5b902 Mon Sep 17 00:00:00 2001 From: Brian Hartvigsen Date: Wed, 12 Feb 2020 12:48:43 -0700 Subject: [PATCH 3/3] Support python2 or python3 using six --- mobilepasser/mobilepasser.py | 6 ++++-- mobilepasser/utils/activation_code.py | 4 +++- mobilepasser/utils/token_generation.py | 10 ++++++---- requirements.txt | 2 +- setup.py | 18 ++++-------------- 5 files changed, 18 insertions(+), 22 deletions(-) diff --git a/mobilepasser/mobilepasser.py b/mobilepasser/mobilepasser.py index 02a381a..bba504e 100755 --- a/mobilepasser/mobilepasser.py +++ b/mobilepasser/mobilepasser.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # coding=utf-8 +from __future__ import print_function + import argparse import os import sys @@ -11,8 +13,8 @@ # Python 2 compatibility. import ConfigParser as configparser -from mobilepasser.utils.activation_code import InvalidActivationKey, MissingActivationKey -from mobilepasser.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") diff --git a/mobilepasser/utils/activation_code.py b/mobilepasser/utils/activation_code.py index 85e1b69..2a290c5 100644 --- a/mobilepasser/utils/activation_code.py +++ b/mobilepasser/utils/activation_code.py @@ -1,5 +1,7 @@ import hashlib +import six + from mobilepasser.utils import base32 from mobilepasser.utils import base32_checksum from mobilepasser.utils.activation_payload_v1 import ActivationPayloadV1 @@ -78,7 +80,7 @@ def computeErrorCode(self, value): hash = hashlib.new('sha256') hash.update(value.tobytes()) - return hash.digest()[-1] + return six.indexbytes(hash.digest(),-1) def getEntropy(self): if self.legacy: diff --git a/mobilepasser/utils/token_generation.py b/mobilepasser/utils/token_generation.py index cb0e209..e1a640a 100644 --- a/mobilepasser/utils/token_generation.py +++ b/mobilepasser/utils/token_generation.py @@ -6,6 +6,8 @@ import hmac import sys +import six + from mobilepasser.utils.activation_code import ActivationCode # I ported the KDF1 algorithm from the bouncycastle library that shipped with @@ -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), encoding='utf8')) - hash.update(bytes(chr((counter >> 16) & 0xff), encoding='utf8')) - hash.update(bytes(chr((counter >> 8) & 0xff), encoding='utf8')) - hash.update(bytes(chr(counter & 0xff), encoding='utf8')) + 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) 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',] },