From 215888886607a6cd91546d83344720188ff1038a Mon Sep 17 00:00:00 2001 From: Ernest W Durbin III Date: Tue, 13 Feb 2018 19:22:27 -0500 Subject: [PATCH 1/4] style: flake8 --- decrypt_otpauth.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/decrypt_otpauth.py b/decrypt_otpauth.py index afa4d4e..a98df9c 100644 --- a/decrypt_otpauth.py +++ b/decrypt_otpauth.py @@ -16,6 +16,7 @@ from Crypto.Cipher import AES from rncryptor import RNCryptor from rncryptor import bord + class Type(Enum): Unknown = 0 HOTP = 1 @@ -128,6 +129,7 @@ archiver.update_class_map({'NSMutableString': MutableString}) archiver.update_class_map({'ACOTPFolder': OTPFolder}) archiver.update_class_map({'ACOTPAccount': OTPAccount}) + class RawRNCryptor(RNCryptor): def post_decrypt_data(self, data): @@ -136,6 +138,7 @@ class RawRNCryptor(RNCryptor): data = data[:-bord(data[-1])] return data + class DangerousUnarchive(archiver.Unarchive): def decode_object(self, index): @@ -204,11 +207,12 @@ def decrypt_account(encrypted_otpauth_account): else: print('Encountered unknow file version', archive['Version']) return - + render_qr_to_terminal(account.otp_uri(), account.type, account.issuer, account.label) + def decrypt_account_11(archive, password): - # Get IV and key for actual archive + # Get IV and key for actual archive iv = hashlib.sha1(archive['IV']).digest()[:16] salt = archive['Salt'] key = hashlib.sha256((salt + '-' + password).encode('utf-8')).digest() @@ -223,6 +227,7 @@ def decrypt_account_11(archive, password): # Construct OTPAccount object from returned dictionary return OTPAccount.from_dict(archive) + def decrypt_account_12(archive, password): # Decrypt using RNCryptor data = data = RawRNCryptor().decrypt(archive['Data'], password) @@ -233,6 +238,7 @@ def decrypt_account_12(archive, password): # Construct OTPAccount object from returned dictionary return OTPAccount.from_dict(archive) + @cli.command() @click.option('--encrypted-otpauth-backup', help="path to your encrypted OTP Auth backup (.otpauthdb)", @@ -265,8 +271,9 @@ def decrypt_backup(encrypted_otpauth_backup): render_qr_to_terminal(account.otp_uri(), account.type, account.issuer, account.label) input("Press Enter to continue...") + def decrypt_backup_10(archive, password): - # Get IV and key for actual archive + # Get IV and key for actual archive iv = hashlib.sha1(archive['IV'].encode('utf-8')).digest()[:16] salt = archive['Salt'] key = hashlib.sha256((salt + '-' + password).encode('utf-8')).digest() @@ -280,6 +287,7 @@ def decrypt_backup_10(archive, password): return [account for folder in archive['Folders'] for account in folder.accounts] + def decrypt_backup_11(archive, password): # Decrypt using RNCryptor data = data = RawRNCryptor().decrypt(archive['WrappedData'], password) @@ -289,5 +297,6 @@ def decrypt_backup_11(archive, password): return [account for folder in archive['Folders'] for account in folder.accounts] + if __name__ == '__main__': cli() From 61b63fe88d50112df441c36c0f8dc50ae7f9083c Mon Sep 17 00:00:00 2001 From: Ernest W Durbin III Date: Tue, 13 Feb 2018 19:37:28 -0500 Subject: [PATCH 2/4] style: use click.echo instead of print, f-strings instead of implicit concatenation --- decrypt_otpauth.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/decrypt_otpauth.py b/decrypt_otpauth.py index a98df9c..ccc9b35 100644 --- a/decrypt_otpauth.py +++ b/decrypt_otpauth.py @@ -205,7 +205,7 @@ def decrypt_account(encrypted_otpauth_account): elif archive['Version'] == 1.2: account = decrypt_account_12(archive, password) else: - print('Encountered unknow file version', archive['Version']) + click.echo(f'Encountered unknow file version: {archive["Version"]}') return render_qr_to_terminal(account.otp_uri(), account.type, account.issuer, account.label) @@ -264,7 +264,7 @@ def decrypt_backup(encrypted_otpauth_backup): elif archive['Version'] == 1.1: accounts = decrypt_backup_11(archive, password) else: - print('Encountered unknow file version', archive['Version']) + click.echo(f'Encountered unknow file version: {archive["Version"]}') return for account in accounts: From f6186f411e236961ce6dcbd0b2a14beab6b31559 Mon Sep 17 00:00:00 2001 From: Ernest W Durbin III Date: Tue, 13 Feb 2018 19:37:54 -0500 Subject: [PATCH 3/4] Create valid OTP QR Codes! --- decrypt_otpauth.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/decrypt_otpauth.py b/decrypt_otpauth.py index ccc9b35..5b7aeea 100644 --- a/decrypt_otpauth.py +++ b/decrypt_otpauth.py @@ -22,6 +22,15 @@ class Type(Enum): HOTP = 1 TOTP = 2 + @property + def uri_value(self): + if self.value == 0: + return 'unknown' + if self.value == 1: + return 'hotp' + if self.value == 2: + return 'totp' + class Algorithm(Enum): Unknown = 0 @@ -110,7 +119,7 @@ class OTPAccount: return OTPAccount(label, issuer, secret, type, algorithm, digits, counter, period, refDate) def otp_uri(self): - otp_type = self.type + otp_type = self.type.uri_value otp_label = quote(f'{self.issuer}:{self.label}') otp_parameters = { 'secret': base64.b32encode(self.secret).decode("utf-8"), From cfbcc97e9d2de75d943b8651b2bab5990185e5c1 Mon Sep 17 00:00:00 2001 From: Ernest W Durbin III Date: Tue, 13 Feb 2018 19:44:28 -0500 Subject: [PATCH 4/4] Remove padding on Base32 encoded per spec. --- decrypt_otpauth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/decrypt_otpauth.py b/decrypt_otpauth.py index 5b7aeea..8598948 100644 --- a/decrypt_otpauth.py +++ b/decrypt_otpauth.py @@ -122,7 +122,7 @@ class OTPAccount: otp_type = self.type.uri_value otp_label = quote(f'{self.issuer}:{self.label}') otp_parameters = { - 'secret': base64.b32encode(self.secret).decode("utf-8"), + 'secret': base64.b32encode(self.secret).decode("utf-8").rstrip("="), 'algorithm': self.algorithm, 'period': self.period, 'digits': self.digits,