def load(ctrl, hw_type: HWType, hw_device_id: str, strength: int, passphrase_enabled: bool, pin_enabled: bool, hw_label: str) -> Tuple[Optional[str], bool]: ctrl.dlg_config_fun(dlg_title="Please confirm", show_progress_bar=False) ctrl.display_msg_fun( '<b>Read the messages displyed on your hardware wallet <br>' 'and click the confirmation button when necessary...</b>') if hw_device_id: if hw_type == HWType.trezor: from hw_intf_trezor import reset_device return reset_device(hw_device_id, strength, passphrase_enabled, pin_enabled, hw_label) elif hw_type == HWType.keepkey: from hw_intf_keepkey import reset_device return reset_device(hw_device_id, strength, passphrase_enabled, pin_enabled, hw_label) else: raise Exception('Not supported by Ledger Nano S.') else: raise HWNotConnectedException()
def load(ctrl, hw_device_id: str, mnemonic: str, pin: str, passphrase_enbled: bool, hw_label: str) -> \ Tuple[Optional[str], bool]: ctrl.dlg_config_fun(dlg_title="Please confirm", show_progress_bar=False) ctrl.display_msg_fun( '<b>Read the messages displyed on your hardware wallet <br>' 'and click the confirmation button when necessary...</b>') if hw_device_id: if hw_type == HWType.trezor: raise Exception('Feature no longer available for Trezor') elif hw_type == HWType.keepkey: from hw_intf_keepkey import load_device_by_mnemonic return load_device_by_mnemonic(hw_device_id, mnemonic, pin, passphrase_enbled, hw_label) else: raise Exception('Not supported by Ledger Nano S.') else: raise HWNotConnectedException()
def read_file_encrypted( file_name: str, ret_attrs: dict, hw_session: HwSessionInfo) -> Generator[bytes, None, None]: ret_attrs['encrypted'] = False try: hw_session.save_state() with open(file_name, 'rb') as f_ptr: data = f_ptr.read(len(DMT_ENCRYPTED_DATA_PREFIX)) if data == DMT_ENCRYPTED_DATA_PREFIX: ret_attrs['encrypted'] = True protocol = read_varint_from_file(f_ptr) if protocol == 1: # with Trezor method + Fernet hw_type_bin = read_varint_from_file(f_ptr) hw_type = { 1: HWType.trezor, 2: HWType.keepkey, 3: HWType.ledger_nano }.get(hw_type_bin) if hw_type: # connect hardware wallet, choosing the type compatible with the type read from # the encrypted file if hw_session.hw_client: if (hw_type in (HWType.trezor, HWType.keepkey) and hw_session.hw_type not in (HWType.trezor, HWType.keepkey)) or \ (hw_type == HWType.ledger_nano and hw_type != hw_session.hw_type): # if the currently connected hardware wallet type is not compatible with the # type from the encrypted file, disconnect it to give a user a chance to choose # the correct one in the code below hw_session.disconnect_hardware_wallet() if not hw_session.hw_client: if hw_type in (HWType.trezor, HWType.keepkey): hw_session.set_hw_types_allowed( (HWType.trezor, HWType.keepkey)) else: hw_session.set_hw_types_allowed((hw_type, )) if not hw_session.connect_hardware_wallet(): raise HWNotConnectedException( f'This file was encrypted with {HWType.get_desc(hw_type)} hardware wallet, ' f'which has to be connected to the computer decrypt the file.' ) data_label_bin = read_bytes_from_file(f_ptr) label = base64.urlsafe_b64decode( data_label_bin).decode('utf-8') encrypted_key_bin = read_bytes_from_file(f_ptr) bip32_path_n = read_int_list_from_file(f_ptr) pub_key_hash_hdr = read_bytes_from_file(f_ptr) while True: if not hw_session.hw_client: raise HWNotConnectedException( f'This file was encrypted with {HWType.get_desc(hw_type)} hardware wallet, ' f'which has to be connected to the computer decrypt the file.' ) if hw_session.hw_type in (HWType.trezor, HWType.keepkey): key_bin, pub_key = hw_session.hw_decrypt_value( bip32_path_n, label=label, value=encrypted_key_bin) elif hw_session.hw_type == HWType.ledger_nano: display_label = f'<b>Click the sign message confirmation button on the <br>' \ f'hardware wallet to decrypt \'{label}\'.</b>' bip32_path_str = bip32_path_n_to_string( bip32_path_n) sig = hw_sign_message( hw_session, 'Dash', bip32_path_str, encrypted_key_bin.hex(), display_label=display_label) adr_pk = get_address_and_pubkey( hw_session, 'Dash', bip32_path_str) pub_key = adr_pk.get('publicKey') key_bin = SHA256.new(sig.signature).digest() else: raise Exception( 'Invalid hardware wallet type.') pub_key_hash = SHA256.new(pub_key).digest() if pub_key_hash_hdr == pub_key_hash: break url = get_note_url('DMT0003') if WndUtils.query_dlg( message= 'Inconsistency between encryption and decryption keys.\n\n' 'The reason may be using a different passphrase than it was used ' 'for encryption or running another application communicating with the ' 'device simultaneously, like Trezor web wallet (see <a href="{url}">' 'here</a>).\n\n' 'Do you want to try again?', buttons=QMessageBox.Yes | QMessageBox.Cancel, default_button=QMessageBox.Cancel, icon=QMessageBox.Warning ) == QMessageBox.Cancel: raise CancelException('User cancelled.') hw_session.disconnect_hardware_wallet() hw_session.connect_hardware_wallet() key = base64.urlsafe_b64encode(key_bin) fer = Fernet(key) while True: # data is written in blocks; if front of each block there is a block size value data_bin = f_ptr.read(8) if len(data_bin) == 0: break # end of file elif len(data_bin) < 8: raise ValueError( 'File end before read completed.') data_chunk_size = int.from_bytes( data_bin, byteorder='little') if data_chunk_size < 0 or data_chunk_size > 2000000000: raise ValueError( 'Data corrupted: invalid data chunk size.') data_bin = f_ptr.read(data_chunk_size) if data_chunk_size != len(data_bin): raise ValueError( 'File end before read completed.') data_base64 = base64.urlsafe_b64encode(data_bin) try: data_decr = fer.decrypt(data_base64) except InvalidToken: raise Exception( 'Couldn\'t decrypt file (InvalidToken error). The file is probably ' 'corrupted or is encrypted with a different encryption method.' ) yield data_decr else: raise ValueError('Invalid hardware wallet type value.') else: raise ValueError('Invalid protocol value.') else: # the data inside the file isn't encrypted # read and yield raw data while True: # data is written in blocks; if front of each block there is a block size value data += f_ptr.read(ENC_FILE_BLOCK_SIZE) if not len(data): break yield data data = bytes() finally: hw_session.restore_state()
def catch_hw_client(*args, **kwargs): hw_session: HwSessionInfo = args[0] client = hw_session.hw_client if not client: client = hw_session.hw_connect() if not client: raise HWNotConnectedException() try: try: # protect against simultaneous access to the same device from different threads hw_session.acquire_client() control_trezor_keepkey_libs(hw_session.hw_type) if hw_session.hw_type == HWType.trezor: import hw_intf_trezor as trezor import trezorlib.client as client from trezorlib import exceptions try: ret = func(*args, **kwargs) except exceptions.PinException as e: raise HardwareWalletPinException(e.args[1]) elif hw_session.hw_type == HWType.keepkey: import hw_intf_keepkey as keepkey import keepkeylib.client as client try: ret = func(*args, **kwargs) except client.PinException as e: raise HardwareWalletPinException(e.args[1]) elif hw_session.hw_type == HWType.ledger_nano_s: ret = func(*args, **kwargs) else: raise Exception('Uknown hardware wallet type: ' + hw_session.hw_type) finally: hw_session.release_client() except (OSError, usb1.USBErrorNoDevice) as e: logging.exception('Exception calling %s function' % func.__name__) logging.info('Disconnecting HW after OSError occurred') hw_session.hw_disconnect() raise HWNotConnectedException( 'The hardware wallet device has been disconnected with the ' 'following error: ' + str(e)) except HardwareWalletPinException: raise except CancelException: raise except Exception as e: logging.exception('Exception calling %s function' % func.__name__) raise return ret