コード例 #1
0
async def _finish_recovery_dry_run(ctx: wire.GenericContext, secret: bytes,
                                   backup_type: EnumTypeBackupType) -> Success:
    if backup_type is None:
        raise RuntimeError

    digest_input = sha256(secret).digest()
    stored = mnemonic.get_secret()
    digest_stored = sha256(stored).digest()
    result = utils.consteq(digest_stored, digest_input)

    is_slip39 = backup_types.is_slip39_backup_type(backup_type)
    # Check that the identifier and iteration exponent match as well
    if is_slip39:
        result &= (storage_device.get_slip39_identifier() ==
                   storage_recovery.get_slip39_identifier())
        result &= (storage_device.get_slip39_iteration_exponent() ==
                   storage_recovery.get_slip39_iteration_exponent())

    await layout.show_dry_run_result(ctx, result, is_slip39)

    storage_recovery.end_progress()

    if result:
        return Success("The seed is valid and matches the one in the device")
    else:
        raise wire.ProcessError(
            "The seed does not match the one in the device")
コード例 #2
0
async def _finish_recovery(
    ctx: wire.GenericContext, secret: bytes, backup_type: EnumTypeBackupType
) -> Success:
    if backup_type is None:
        raise RuntimeError

    storage_device.store_mnemonic_secret(
        secret, backup_type, needs_backup=False, no_backup=False
    )
    if backup_type in (BackupType.Slip39_Basic, BackupType.Slip39_Advanced):
        identifier = storage_recovery.get_slip39_identifier()
        exponent = storage_recovery.get_slip39_iteration_exponent()
        if identifier is None or exponent is None:
            # Identifier and exponent need to be stored in storage at this point
            raise RuntimeError
        storage_device.set_slip39_identifier(identifier)
        storage_device.set_slip39_iteration_exponent(exponent)

    await show_success(ctx, ("You have successfully", "recovered your wallet."))

    storage_recovery.end_progress()
    return Success(message="Device recovered")
コード例 #3
0
def process_slip39(words: str) -> Tuple[Optional[bytes], slip39.Share]:
    """
    Processes a single mnemonic share. Returns the encrypted master secret
    (or None if more shares are needed) and the share's group index and member index.
    """
    share = slip39.decode_mnemonic(words)

    remaining = storage_recovery.fetch_slip39_remaining_shares()

    # if this is the first share, parse and store metadata
    if not remaining:
        storage_recovery.set_slip39_group_count(share.group_count)
        storage_recovery.set_slip39_iteration_exponent(share.iteration_exponent)
        storage_recovery.set_slip39_identifier(share.identifier)
        storage_recovery.set_slip39_remaining_shares(
            share.threshold - 1, share.group_index
        )
        storage_recovery_shares.set(share.index, share.group_index, words)

        # if share threshold and group threshold are 1
        # we can calculate the secret right away
        if share.threshold == 1 and share.group_threshold == 1:
            identifier, iteration_exponent, secret, _ = slip39.combine_mnemonics(
                [words]
            )
            return secret, share
        else:
            # we need more shares
            return None, share

    # These should be checked by UI before so it's a Runtime exception otherwise
    if share.identifier != storage_recovery.get_slip39_identifier():
        raise RuntimeError("Slip39: Share identifiers do not match")
    if share.iteration_exponent != storage_recovery.get_slip39_iteration_exponent():
        raise RuntimeError("Slip39: Share exponents do not match")
    if storage_recovery_shares.get(share.index, share.group_index):
        raise RuntimeError("Slip39: This mnemonic was already entered")
    if share.group_count != storage_recovery.get_slip39_group_count():
        raise RuntimeError("Slip39: Group count does not match")

    remaining_for_share = (
        storage_recovery.get_slip39_remaining_shares(share.group_index)
        or share.threshold
    )
    storage_recovery.set_slip39_remaining_shares(
        remaining_for_share - 1, share.group_index
    )
    remaining[share.group_index] = remaining_for_share - 1
    storage_recovery_shares.set(share.index, share.group_index, words)

    if remaining.count(0) < share.group_threshold:
        # we need more shares
        return None, share

    if share.group_count > 1:
        mnemonics = []
        for i, r in enumerate(remaining):
            # if we have multiple groups pass only the ones with threshold reached
            if r == 0:
                group = storage_recovery_shares.fetch_group(i)
                mnemonics.extend(group)
    else:
        # in case of slip39 basic we only need the first and only group
        mnemonics = storage_recovery_shares.fetch_group(0)

    identifier, iteration_exponent, secret, _ = slip39.combine_mnemonics(mnemonics)
    return secret, share