Пример #1
0
def process_all(mnemonics: list) -> bytes:
    """
    Receives all mnemonics and processes it into pre-master secret which is usually then
    stored in the storage.
    """
    identifier, iteration_exponent, secret = slip39.combine_mnemonics(
        mnemonics)
    storage.set_slip39_iteration_exponent(iteration_exponent)
    storage.set_slip39_identifier(identifier)
    return secret
Пример #2
0
def generate_from_secret(master_secret: bytes, count: int,
                         threshold: int) -> str:
    """
    Generates new Shamir backup for 'master_secret'. Multiple groups are not yet supported.
    """
    identifier, group_mnemonics = slip39.generate_single_group_mnemonics_from_data(
        master_secret, threshold, count)
    storage.set_slip39_iteration_exponent(slip39.DEFAULT_ITERATION_EXPONENT)
    storage.set_slip39_identifier(identifier)
    return group_mnemonics
Пример #3
0
def process_single(mnemonic: str) -> bytes:
    """
    Receives single mnemonic and processes it. Returns what is then stored in storage or
    None if more shares are needed.
    """
    identifier, iteration_exponent, _, _, _, index, threshold, value = slip39.decode_mnemonic(
        mnemonic)  # TODO: use better data structure for this
    if threshold == 1:
        raise ValueError("Threshold equal to 1 is not allowed.")

    # if recovery is not in progress already, start it and wait for more mnemonics
    if not storage.is_slip39_in_progress():
        storage.set_slip39_in_progress(True)
        storage.set_slip39_iteration_exponent(iteration_exponent)
        storage.set_slip39_identifier(identifier)
        storage.set_slip39_threshold(threshold)
        storage.set_slip39_remaining(threshold - 1)
        storage.set_slip39_words_count(len(mnemonic.split()))
        storage.set_slip39_mnemonic(index, mnemonic)
        return None  # we need more shares

    # check identifier and member index of this share against stored values
    if identifier != storage.get_slip39_identifier():
        # TODO: improve UX (tell user)
        raise ValueError("Share identifiers do not match")
    if storage.get_slip39_mnemonic(index):
        # TODO: improve UX (tell user)
        raise ValueError("This mnemonic was already entered")

    # append to storage
    remaining = storage.get_slip39_remaining() - 1
    storage.set_slip39_remaining(remaining)
    storage.set_slip39_mnemonic(index, mnemonic)
    if remaining != 0:
        return None  # we need more shares

    # combine shares and return the master secret
    mnemonics = storage.get_slip39_mnemonics()
    if len(mnemonics) != threshold:
        raise ValueError("Some mnemonics are still missing.")
    _, _, secret = slip39.combine_mnemonics(mnemonics)
    return secret
Пример #4
0
async def reset_device(ctx, msg):
    # validate parameters and device state
    _validate_reset_device(msg)

    # make sure user knows he's setting up a new wallet
    await layout.show_reset_device_warning(ctx, msg.slip39)

    # request new PIN
    if msg.pin_protection:
        newpin = await request_pin_confirm(ctx)
    else:
        newpin = ""

    # generate and display internal entropy
    int_entropy = random.bytes(32)
    if __debug__:
        debug.reset_internal_entropy = int_entropy
    if msg.display_random:
        await layout.show_internal_entropy(ctx, int_entropy)

    # request external entropy and compute the master secret
    entropy_ack = await ctx.call(EntropyRequest(), MessageType.EntropyAck)
    ext_entropy = entropy_ack.entropy
    secret = _compute_secret_from_entropy(int_entropy, ext_entropy,
                                          msg.strength)

    if msg.slip39:
        storage.set_slip39_identifier(slip39.generate_random_identifier())
        storage.set_slip39_iteration_exponent(
            slip39.DEFAULT_ITERATION_EXPONENT)

    # should we back up the wallet now?
    if not msg.no_backup and not msg.skip_backup:
        if not await layout.confirm_backup(ctx):
            if not await layout.confirm_backup_again(ctx):
                msg.skip_backup = True

    # generate and display backup information for the master secret
    if not msg.no_backup and not msg.skip_backup:
        if msg.slip39:
            await backup_slip39_wallet(ctx, secret)
        else:
            await backup_bip39_wallet(ctx, secret)

    # write PIN into storage
    if not config.change_pin(pin_to_int(""), pin_to_int(newpin)):
        raise wire.ProcessError("Could not change PIN")

    # write settings and master secret into storage
    storage.load_settings(label=msg.label,
                          use_passphrase=msg.passphrase_protection)
    if msg.slip39:
        mnemonic.slip39.store(secret=secret,
                              needs_backup=msg.skip_backup,
                              no_backup=msg.no_backup)
    else:
        # in BIP-39 we store mnemonic string instead of the secret
        mnemonic.bip39.store(
            secret=bip39.from_data(secret).encode(),
            needs_backup=msg.skip_backup,
            no_backup=msg.no_backup,
        )

    # if we backed up the wallet, show success message
    if not msg.no_backup and not msg.skip_backup:
        await layout.show_backup_success(ctx)

    return Success(message="Initialized")