Пример #1
0
async def _init_step(s: LiveRefreshState, ctx,
                     msg: MoneroLiveRefreshStartRequest, keychain):
    await paths.validate_path(ctx, misc.validate_full_path, path=msg.address_n)

    await confirms.require_confirm_live_refresh(ctx)

    s.creds = misc.get_creds(keychain, msg.address_n, msg.network_type)

    return MoneroLiveRefreshStartAck()
Пример #2
0
async def get_watch_only(ctx, msg: MoneroGetWatchKey, keychain):
    await paths.validate_path(ctx, keychain, msg.address_n)

    await confirms.require_confirm_watchkey(ctx)

    creds = misc.get_creds(keychain, msg.address_n, msg.network_type)
    address = creds.address
    watch_key = crypto.encodeint(creds.view_key_private)

    return MoneroWatchKey(watch_key=watch_key, address=address)
Пример #3
0
async def _init_step(s: LiveRefreshState, ctx,
                     msg: MoneroLiveRefreshStartRequest, keychain):
    await paths.validate_path(ctx, keychain, msg.address_n)

    if not storage.cache.get(storage.cache.APP_MONERO_LIVE_REFRESH):
        await confirms.require_confirm_live_refresh(ctx)
        storage.cache.set(storage.cache.APP_MONERO_LIVE_REFRESH, b"\x01")

    s.creds = misc.get_creds(keychain, msg.address_n, msg.network_type)

    return MoneroLiveRefreshStartAck()
Пример #4
0
async def get_watch_only(
    ctx: Context, msg: MoneroGetWatchKey, keychain: Keychain
) -> MoneroWatchKey:
    await paths.validate_path(ctx, keychain, msg.address_n)

    await layout.require_confirm_watchkey(ctx)

    creds = misc.get_creds(keychain, msg.address_n, msg.network_type)
    address = creds.address
    watch_key = crypto_helpers.encodeint(creds.view_key_private)

    return MoneroWatchKey(watch_key=watch_key, address=address.encode())
Пример #5
0
async def _init_step(s: LiveRefreshState, ctx,
                     msg: MoneroLiveRefreshStartRequest, keychain):
    await paths.validate_path(ctx, misc.validate_full_path, keychain,
                              msg.address_n, CURVE)

    passphrase_fprint = get_passphrase_fprint()
    if live_refresh_token() != passphrase_fprint:
        await confirms.require_confirm_live_refresh(ctx)
        live_refresh_token(passphrase_fprint)

    s.creds = misc.get_creds(keychain, msg.address_n, msg.network_type)

    return MoneroLiveRefreshStartAck()
Пример #6
0
async def get_address(ctx: wire.Context, msg: MoneroGetAddress,
                      keychain: Keychain) -> MoneroAddress:
    await paths.validate_path(ctx, keychain, msg.address_n)

    creds = misc.get_creds(keychain, msg.address_n, msg.network_type)
    addr = creds.address

    have_subaddress = msg.account is not None and msg.minor is not None
    have_payment_id = msg.payment_id is not None

    if (msg.account is None) != (msg.minor is None):
        raise wire.ProcessError("Invalid subaddress indexes")

    if have_payment_id and have_subaddress:
        raise wire.DataError("Subaddress cannot be integrated")

    if have_payment_id:
        assert msg.payment_id is not None
        if len(msg.payment_id) != 8:
            raise ValueError("Invalid payment ID length")
        addr = addresses.encode_addr(
            net_version(msg.network_type, False, True),
            crypto_helpers.encodepoint(creds.spend_key_public),
            crypto_helpers.encodepoint(creds.view_key_public),
            msg.payment_id,
        )

    if have_subaddress:
        assert msg.account is not None
        assert msg.minor is not None

        pub_spend, pub_view = monero.generate_sub_address_keys(
            creds.view_key_private, creds.spend_key_public, msg.account,
            msg.minor)

        addr = addresses.encode_addr(
            net_version(msg.network_type, True, False),
            crypto_helpers.encodepoint(pub_spend),
            crypto_helpers.encodepoint(pub_view),
        )

    if msg.show_display:
        title = paths.address_n_to_str(msg.address_n)
        await show_address(
            ctx,
            address=addr,
            address_qr="monero:" + addr,
            title=title,
        )

    return MoneroAddress(address=addr.encode())
Пример #7
0
async def get_address(ctx, msg, keychain):
    await paths.validate_path(ctx, misc.validate_full_path, keychain, msg.address_n)

    creds = misc.get_creds(keychain, msg.address_n, msg.network_type)

    if msg.show_display:
        desc = address_n_to_str(msg.address_n)
        while True:
            if await show_address(ctx, creds.address.decode(), desc=desc):
                break
            if await show_qr(ctx, creds.address.decode(), desc=desc):
                break

    return MoneroAddress(address=creds.address)
Пример #8
0
async def get_tx_keys(ctx: wire.Context, msg: MoneroGetTxKeyRequest,
                      keychain: Keychain) -> MoneroGetTxKeyAck:
    await paths.validate_path(ctx, keychain, msg.address_n)

    do_deriv = msg.reason == _GET_TX_KEY_REASON_TX_DERIVATION
    await layout.require_confirm_tx_key(ctx, export_key=not do_deriv)

    creds = misc.get_creds(keychain, msg.address_n, msg.network_type)

    tx_enc_key = misc.compute_tx_key(
        creds.spend_key_private,
        msg.tx_prefix_hash,
        msg.salt1,
        crypto_helpers.decodeint(msg.salt2),
    )

    # the plain_buff first stores the tx_priv_keys as decrypted here
    # and then is used to store the derivations if applicable
    plain_buff = chacha_poly.decrypt_pack(tx_enc_key, msg.tx_enc_keys)
    utils.ensure(len(plain_buff) % 32 == 0, "Tx key buffer has invalid size")
    msg.tx_enc_keys = b""

    # If return only derivations do tx_priv * view_pub
    if do_deriv:
        if msg.view_public_key is None:
            raise wire.DataError("Missing view public key")

        plain_buff = bytearray(plain_buff)
        view_pub = crypto_helpers.decodepoint(msg.view_public_key)
        tx_priv = crypto.Scalar()
        derivation = crypto.Point()
        n_keys = len(plain_buff) // 32
        for c in range(n_keys):
            crypto.decodeint_into(tx_priv, plain_buff, 32 * c)
            crypto.scalarmult_into(derivation, view_pub, tx_priv)
            crypto.encodepoint_into(plain_buff, derivation, 32 * c)

    # Encrypt by view-key based password.
    tx_enc_key_host, salt = misc.compute_enc_key_host(creds.view_key_private,
                                                      msg.tx_prefix_hash)

    res = chacha_poly.encrypt_pack(tx_enc_key_host, plain_buff)
    res_msg = MoneroGetTxKeyAck(salt=salt)
    if do_deriv:
        res_msg.tx_derivations = res
        return res_msg

    res_msg.tx_keys = res
    return res_msg
Пример #9
0
async def _init_step(s, ctx, msg, keychain):
    await paths.validate_path(ctx, misc.validate_full_path, path=msg.address_n)

    s.creds = misc.get_creds(keychain, msg.address_n, msg.network_type)

    await confirms.require_confirm_keyimage_sync(ctx)

    s.num_outputs = msg.num
    s.expected_hash = msg.hash
    s.enc_key = crypto.random_bytes(32)

    for sub in msg.subs:
        monero.compute_subaddresses(s.creds, sub.account, sub.minor_indices,
                                    s.subaddresses)

    return MoneroKeyImageExportInitAck()
Пример #10
0
async def get_address(ctx, msg, keychain):
    await paths.validate_path(ctx, keychain, msg.address_n)

    creds = misc.get_creds(keychain, msg.address_n, msg.network_type)
    addr = creds.address

    if msg.payment_id:
        if len(msg.payment_id) != 8:
            raise ValueError("Invalid payment ID length")
        addr = addresses.encode_addr(
            net_version(msg.network_type, False, True),
            crypto.encodepoint(creds.spend_key_public),
            crypto.encodepoint(creds.view_key_public),
            msg.payment_id,
        )

    if msg.account or msg.minor:
        if msg.payment_id:
            raise ValueError("Subaddress cannot be integrated")

        pub_spend, pub_view = monero.generate_sub_address_keys(
            creds.view_key_private, creds.spend_key_public, msg.account,
            msg.minor)

        addr = addresses.encode_addr(
            net_version(msg.network_type, True, False),
            crypto.encodepoint(pub_spend),
            crypto.encodepoint(pub_view),
        )

    if msg.show_display:
        title = paths.address_n_to_str(msg.address_n)
        await show_address(
            ctx,
            address=addr.decode(),
            address_qr="monero:" + addr.decode(),
            title=title,
        )

    return MoneroAddress(address=addr)
async def init_transaction(
    state: State,
    address_n: list,
    network_type: int,
    tsx_data: MoneroTransactionData,
    keychain,
) -> MoneroTransactionInitAck:
    from apps.monero.signing import offloading_keys
    from apps.common import paths

    await paths.validate_path(state.ctx, misc.validate_full_path, keychain,
                              address_n, CURVE)

    state.creds = misc.get_creds(keychain, address_n, network_type)
    state.client_version = tsx_data.client_version or 0
    if state.client_version == 0:
        raise ValueError("Client version not supported")

    state.fee = state.fee if state.fee > 0 else 0
    state.tx_priv = crypto.random_scalar()
    state.tx_pub = crypto.scalarmult_base(state.tx_priv)
    state.mem_trace(1)

    state.input_count = tsx_data.num_inputs
    state.output_count = len(tsx_data.outputs)
    state.progress_total = 4 + 3 * state.input_count + state.output_count
    state.progress_cur = 0

    # Ask for confirmation
    await confirms.require_confirm_transaction(state.ctx, state, tsx_data,
                                               state.creds.network_type)
    state.creds.address = None
    state.creds.network_type = None
    gc.collect()
    state.mem_trace(3)

    # Basic transaction parameters
    state.output_change = tsx_data.change_dts
    state.mixin = tsx_data.mixin
    state.fee = tsx_data.fee
    state.account_idx = tsx_data.account
    state.last_step = state.STEP_INIT
    if tsx_data.hard_fork:
        state.hard_fork = tsx_data.hard_fork

    # Ensure change is correct
    _check_change(state, tsx_data.outputs)

    # At least two outpus are required, this applies also for sweep txs
    # where one fake output is added. See _check_change for more info
    if state.output_count < 2:
        raise signing.NotEnoughOutputsError(
            "At least two outputs are required")

    _check_rsig_data(state, tsx_data.rsig_data)
    _check_subaddresses(state, tsx_data.outputs)

    # Extra processing, payment id
    _process_payment_id(state, tsx_data)
    await _compute_sec_keys(state, tsx_data)
    gc.collect()

    # Iterative tx_prefix_hash hash computation
    state.tx_prefix_hasher.uvarint(
        2)  # current Monero transaction format (RingCT = 2)
    state.tx_prefix_hasher.uvarint(tsx_data.unlock_time)
    state.tx_prefix_hasher.uvarint(state.input_count)  # ContainerType, size
    state.mem_trace(10, True)

    # Final message hasher
    state.full_message_hasher.init()
    state.full_message_hasher.set_type_fee(signing.RctType.Bulletproof2,
                                           state.fee)

    # Sub address precomputation
    if tsx_data.account is not None and tsx_data.minor_indices:
        _precompute_subaddr(state, tsx_data.account, tsx_data.minor_indices)
    state.mem_trace(5, True)

    # HMACs all outputs to disallow tampering.
    # Each HMAC is then sent alongside the output
    # and trezor validates it.
    hmacs = []
    for idx in range(state.output_count):
        c_hmac = await offloading_keys.gen_hmac_tsxdest(
            state.key_hmac, tsx_data.outputs[idx], idx)
        hmacs.append(c_hmac)
        gc.collect()

    state.mem_trace(6)

    from trezor.messages.MoneroTransactionInitAck import MoneroTransactionInitAck
    from trezor.messages.MoneroTransactionRsigData import MoneroTransactionRsigData

    rsig_data = MoneroTransactionRsigData(offload_type=state.rsig_offload)

    return MoneroTransactionInitAck(hmacs=hmacs, rsig_data=rsig_data)