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")
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")
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