Merge pull request #3 from ewdurbin/ewdurbin/master

Render valid QR Codes.
This commit is contained in:
Roland Moers
2018-02-15 21:45:22 +01:00
committed by GitHub

View File

@@ -16,11 +16,21 @@ from Crypto.Cipher import AES
from rncryptor import RNCryptor
from rncryptor import bord
class Type(Enum):
Unknown = 0
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
@@ -109,10 +119,10 @@ 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"),
'secret': base64.b32encode(self.secret).decode("utf-8").rstrip("="),
'algorithm': self.algorithm,
'period': self.period,
'digits': self.digits,
@@ -128,6 +138,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 +147,7 @@ class RawRNCryptor(RNCryptor):
data = data[:-bord(data[-1])]
return data
class DangerousUnarchive(archiver.Unarchive):
def decode_object(self, index):
@@ -202,13 +214,14 @@ 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)
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 +236,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 +247,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)",
@@ -258,15 +273,16 @@ 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:
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 +296,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 +306,6 @@ def decrypt_backup_11(archive, password):
return [account for folder in archive['Folders'] for account in folder.accounts]
if __name__ == '__main__':
cli()