def test_core_types(self): self.archive(1) self.archive('two') self.archive(3.14) self.archive([1, 'two', 3.14]) self.archive({'fruit': 'kiwi', 'veg': 'asparagus'}) self.archive(b'hello') self.archive({'data': b'hello'}) self.archive(timestamp(0)) self.archive([timestamp(-4)])
def test_circular_ref(self): obj = FooArchive('herp', timestamp(9001), 42, ['strawberries', 'dragonfruit'], {'key': 'value'}, False, None) obj.recursive = obj plist = plistlib.loads(archiver.archive(obj)) foo_obj = plist['$objects'][1] self.assertEqual(plistlib.UID(1), foo_obj['recurse'])
def test_circular_ref(self): foo = FooArchive('herp', timestamp(9001), 42, ['strawberries', 'dragonfruit'], {'key': 'value'}, False, None) foo.recursive = foo plist = bplist.parse(archiver.archive(foo)) foo_obj = plist['$objects'][1] self.assertEqual(uid(1), foo_obj['recurse'])
def from_andOtpJson(andOtpJson): label = andOtpJson.get("label") issuer = andOtpJson.get("issuer") secret = andOtpJson.get("secret") secret += "=" * ((8 - len(secret) % 8) % 8) secret = base64.b32decode(secret.encode()) type = Type[andOtpJson.get("type")] algorithm = Algorithm[andOtpJson.get("algorithm")] digits = andOtpJson.get("digits") counter = 0 # andOtpJson.get("counter") #not in andOtp json backup period = andOtpJson.get("period") refDate = None # andOtpJson.get("refDate") #not in andOtp json backup hideInWidget = False # andOtpJson.get("hideInWidget") #not in andOtp json backup ID = None #implement ID fkt in for-loop andOtpJson.get("ID") #not in andOtp json backup hideInMacWidget = True # andOtpJson.get("hideInMacWidget") #not in andOtp json backup lastModified = timestamp(time.time()) # andOtpJson.get("lastModified") #not in andOtp json backup icon = None # andOtpJson.get("icon") #not in andOtp json backup macWidgetIndex = -1 # andOtpJson.get("macWidgetIndex") #not in andOtp json backup widgetIndex = None #implement ID fkt in for-loop? #andOtpJson.get("widgetIndex") #not in andOtp json backup return OTPAccount(label, issuer, secret, type, algorithm, digits, counter, period, refDate, hideInWidget, ID, hideInMacWidget, lastModified, icon, macWidgetIndex, widgetIndex)
def test_custom_type(self): foo = FooArchive('herp', timestamp(9001), 42, ['strawberries', 'dragonfruit'], {'key': 'value'}, False, None)
def andotp_to_otpauth(encrypted_andotp_backup): ## Derive output file name from input basename file_basename = os.path.basename(encrypted_andotp_backup.name) filename_without_extension = file_basename.split('.')[0] output_filename = filename_without_extension + '.otpauthdb' ## Get password from user password = getpass.getpass(f'Password for export file {encrypted_andotp_backup.name}: ') ## Read binary data file data = encrypted_andotp_backup.read() ## Get parts of the message containing decryption information iterations=data[:4] iterations=int.from_bytes(iterations, "big") salt=data[4:16] iv=data[16:28] tag=data[-16:] data = data[28:-16] ## Key generation dk = hashlib.pbkdf2_hmac('sha1', password.encode('utf-8'), salt, iterations, dklen=32) ## Decryption cipher = AES.new(dk, AES.MODE_GCM, iv, mac_len=16) try: plaintext = cipher.decrypt_and_verify(data,tag) # print("The message is authentic:", plaintext) except ValueError: print("Key incorrect or message corrupted") ## Create Json data data= json.loads(plaintext.decode('utf-8')) ## Optional Show all account data on Screen (uncomment if desired) # print(json.dumps(data, indent = 4, sort_keys=True)) ## Build OTPAccount Array for OTP Auth from andOTP Json File including ID creation ID =0 accounts = [] for transacc in data: transacc = OTPAccount.from_andOtpJson(transacc) ID += 1 transacc.ID = str(ID) transacc.widgetIndex = ID-1 accounts.append(transacc) ## Create Archive Dict and Folder List for plist OTP Auth Backup File newarchive = {} newarchive['Folders'] = [OTPFolder('Accounts',accounts,'1',timestamp(time.time()))] newarchive['DeletedAccountIDs'] = [] newarchive['DeletedFolderIDs'] = [] ## Achive the inner dict as .plist data newarchive = DangerousArchive(newarchive).to_bytes() ## crypt #1 with user pw from andOTP File data = RawRNCryptor().encrypt(newarchive, password) ## Build and Repack outer Archive to .plist data repack = { "Version" : 1.1, "WrappedData" : data, } repack = DangerousArchive(repack).to_bytes() ## crypt 2 outer with OTP Auth specific details iv = bytes(16) key = hashlib.sha256('Authenticator'.encode('utf-8')).digest() fill=16-len(repack)%16 repack += bytes([fill])*fill data = AES.new(key, AES.MODE_CBC, iv).encrypt(repack) ## Write output file. Same filename as input. Different extension f = open(output_filename, "wb") f.write(bytearray(data)) f.close click.echo(f'Conversion finished. Encrypted with same password from andOTP Backup. Output file name: {output_filename}')