Beispiel #1
0
    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()
Beispiel #2
0
    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()
Beispiel #4
0
    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