Пример #1
0
def test_backup_slip39_basic(client):
    assert client.features.needs_backup is True
    mnemonics = []

    def input_flow():
        # 1. Checklist
        # 2. Number of shares (5)
        # 3. Checklist
        # 4. Threshold (3)
        # 5. Checklist
        # 6. Confirm show seeds
        yield from click_through(client.debug, screens=6, code=B.ResetDevice)

        # Mnemonic phrases
        for _ in range(5):
            yield  # Phrase screen
            mnemonic = read_and_confirm_mnemonic(client.debug, words=20)
            mnemonics.append(mnemonic)
            yield  # Confirm continue to next
            client.debug.press_yes()

        # Confirm backup
        yield
        client.debug.press_yes()

    with client:
        client.set_input_flow(input_flow)
        client.set_expected_responses([
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.Success),
            messages.Success(),
            messages.Features(),
        ])
        device.backup(client)

    client.init_device()
    assert client.features.initialized is True
    assert client.features.needs_backup is False
    assert client.features.unfinished_backup is False
    assert client.features.no_backup is False
    assert client.features.backup_type is messages.BackupType.Slip39_Basic

    expected_ms = shamir.combine_mnemonics(MNEMONIC_SLIP39_BASIC_20_3of6)
    actual_ms = shamir.combine_mnemonics(mnemonics[:3])
    assert expected_ms == actual_ms
def test_backup_slip39_basic(client: Client, click_info: bool):
    assert client.features.needs_backup is True
    mnemonics = []

    def input_flow():
        yield  # Checklist
        client.debug.press_yes()
        if click_info:
            yield from click_info_button(client.debug)
        yield  # Number of shares (5)
        client.debug.press_yes()
        yield  # Checklist
        client.debug.press_yes()
        if click_info:
            yield from click_info_button(client.debug)
        yield  # Threshold (3)
        client.debug.press_yes()
        yield  # Checklist
        client.debug.press_yes()
        yield  # Confirm show seeds
        client.debug.press_yes()

        # Mnemonic phrases
        for _ in range(5):
            # Phrase screen
            mnemonic = yield from read_and_confirm_mnemonic(client.debug)
            mnemonics.append(mnemonic)
            yield  # Confirm continue to next
            client.debug.press_yes()

        yield  # Confirm backup
        client.debug.press_yes()

    with client:
        client.set_input_flow(input_flow)
        client.set_expected_responses(
            [messages.ButtonRequest(code=B.ResetDevice)] *
            (8 if click_info else 6)  # intro screens (and optional info)
            + [
                messages.ButtonRequest(code=B.ResetDevice),
                messages.ButtonRequest(code=B.Success),
            ] * 5  # individual shares
            + [
                messages.ButtonRequest(code=B.Success),
                messages.Success,
                messages.Features,
            ])
        device.backup(client)

    client.init_device()
    assert client.features.initialized is True
    assert client.features.needs_backup is False
    assert client.features.unfinished_backup is False
    assert client.features.no_backup is False
    assert client.features.backup_type is messages.BackupType.Slip39_Basic

    expected_ms = shamir.combine_mnemonics(MNEMONIC_SLIP39_BASIC_20_3of6)
    actual_ms = shamir.combine_mnemonics(mnemonics[:3])
    assert expected_ms == actual_ms
def test_iteration_exponent():
    mnemonics = shamir.generate_mnemonics(1, [(3, 5)], MS, b"TREZOR", 1)[0]
    assert MS == shamir.combine_mnemonics(mnemonics[1:4], b"TREZOR")
    assert MS != shamir.combine_mnemonics(mnemonics[1:4])

    mnemonics = shamir.generate_mnemonics(1, [(3, 5)], MS, b"TREZOR", 2)[0]
    assert MS == shamir.combine_mnemonics(mnemonics[1:4], b"TREZOR")
    assert MS != shamir.combine_mnemonics(mnemonics[1:4])
def validate_mnemonics(mnemonics, threshold, expected_secret):
    # We expect these combinations to recreate the secret properly
    for test_group in combinations(mnemonics, threshold):
        secret = shamir.combine_mnemonics(test_group)
        assert secret == expected_secret
    # We expect these combinations to raise MnemonicError
    for test_group in combinations(mnemonics, threshold - 1):
        with pytest.raises(
            MnemonicError, match=r".*Expected {} mnemonics.*".format(threshold)
        ):
            secret = shamir.combine_mnemonics(test_group)
Пример #5
0
def validate_mnemonics(mnemonics, threshold, expected_ems):
    # We expect these combinations to recreate the secret properly
    for test_group in combinations(mnemonics, threshold):
        # TODO: HOTFIX, we should fix this properly by modifying and unifying the python-shamir-mnemonic API
        ms = shamir.combine_mnemonics(test_group)
        identifier, iteration_exponent, _, _, _ = shamir._decode_mnemonics(test_group)
        ems = shamir._encrypt(ms, b"", iteration_exponent, identifier)
        assert ems == expected_ems
    # We expect these combinations to raise MnemonicError
    for test_group in combinations(mnemonics, threshold - 1):
        with pytest.raises(
            MnemonicError, match=r".*Expected {} mnemonics.*".format(threshold)
        ):
            shamir.combine_mnemonics(test_group)
def test_vectors():
    with open("vectors.json", "r") as f:
        vectors = json.load(f)
    for description, mnemonics, secret in vectors:
        if secret:
            assert bytes.fromhex(secret) == shamir.combine_mnemonics(
                mnemonics,
                b"TREZOR"), 'Incorrect secret for test vector "{}".'.format(
                    description)
        else:
            with pytest.raises(MnemonicError):
                shamir.combine_mnemonics(mnemonics)
                pytest.fail(
                    'Failed to raise exception for test vector "{}".'.format(
                        description))
Пример #7
0
def split_mnemonic(m, n):
    phrase = input('Enter BIP39 phrase:\n')

    is_valid = check_bip39_phrase(phrase)
    if not is_valid:
        print('The BIP39 phrase is invalid.', file=sys.stderr)
        sys.exit(2)

    seed = phrase_to_seed(phrase)

    print_seed(seed)
    print('\nGenerating shares...')
    mnemonics = shamir_mnemonic.generate_mnemonics(1, [(m, n)], seed)[0]

    combinations = [combo for combo in itertools.combinations(mnemonics, m)]

    for combo in combinations:
        secret = shamir_mnemonic.combine_mnemonics(combo)
        if secret != seed:
            print(
                'Error: a combination of shares failed to verify. Try again.',
                file=sys.stderr)
            sys.exit(2)

    return mnemonics
Пример #8
0
def backup_flow_slip39_advanced(client):
    mnemonics = []

    def input_flow():
        # 1. Confirm Reset
        # 2. shares info
        # 3. Set & Confirm number of groups
        # 4. threshold info
        # 5. Set & confirm group threshold value
        # 6-15: for each of 5 groups:
        #   1. Set & Confirm number of shares
        #   2. Set & confirm share threshold value
        # 16. Confirm show seeds
        yield from click_through(client.debug, screens=16, code=B.ResetDevice)

        # show & confirm shares for all groups
        for _ in range(5):
            for _ in range(5):
                # mnemonic phrases
                btn_code = yield
                assert btn_code == B.ResetDevice
                mnemonic = read_and_confirm_mnemonic(client.debug, words=20)
                mnemonics.append(mnemonic)

                # Confirm continue to next share
                btn_code = yield
                assert btn_code == B.Success
                client.debug.press_yes()

        # safety warning
        btn_code = yield
        assert btn_code == B.Success
        client.debug.press_yes()

    with client:
        client.set_input_flow(input_flow)
        client.set_expected_responses(
            [messages.ButtonRequest(code=B.ResetDevice)] * 6  # intro screens
            + [
                messages.ButtonRequest(code=B.ResetDevice),
                messages.ButtonRequest(code=B.ResetDevice),
            ] * 5  # group thresholds
            + [
                messages.ButtonRequest(code=B.ResetDevice),
                messages.ButtonRequest(code=B.Success),
            ] * 25  # individual shares
            + [
                messages.ButtonRequest(code=B.Success),
                messages.Success(),
                messages.Features(),
            ])
        device.backup(client)

    mnemonics = mnemonics[0:3] + mnemonics[5:8] + mnemonics[10:13]
    ms = shamir.combine_mnemonics(mnemonics)
    identifier, iteration_exponent, _, _, _ = shamir._decode_mnemonics(
        mnemonics)
    secret = shamir._encrypt(ms, b"", iteration_exponent, identifier)
    return secret
Пример #9
0
def validate_mnemonics(mnemonics, expected_ems):
    # We expect these combinations to recreate the secret properly
    # In case of click tests the mnemonics are always XofX so no need for combinations
    ms = shamir.combine_mnemonics(mnemonics)
    identifier, iteration_exponent, _, _, _ = shamir._decode_mnemonics(
        mnemonics)
    ems = shamir._encrypt(ms, b"", iteration_exponent, identifier)
    assert ems == expected_ems
Пример #10
0
def validate_mnemonics(mnemonics, threshold, expected_ems):
    # 3of5 shares 3of5 groups
    # TODO: test all possible group+share combinations?
    test_combination = mnemonics[0:3] + mnemonics[5:8] + mnemonics[10:13]
    ms = shamir.combine_mnemonics(test_combination)
    identifier, iteration_exponent, _, _, _ = shamir._decode_mnemonics(test_combination)
    ems = shamir._encrypt(ms, b"", iteration_exponent, identifier)
    assert ems == expected_ems
Пример #11
0
def test_group_sharing():
    group_threshold = 2
    group_sizes = (5, 3, 5, 1)
    member_thresholds = (3, 2, 2, 1)
    mnemonics = shamir.generate_mnemonics(
        group_threshold, list(zip(member_thresholds, group_sizes)), MS)

    # Test all valid combinations of mnemonics.
    for groups in combinations(zip(mnemonics, member_thresholds),
                               group_threshold):
        for group1_subset in combinations(groups[0][0], groups[0][1]):
            for group2_subset in combinations(groups[1][0], groups[1][1]):
                mnemonic_subset = list(group1_subset + group2_subset)
                shuffle(mnemonic_subset)
                assert MS == shamir.combine_mnemonics(mnemonic_subset)

    # Minimal sets of mnemonics.
    assert MS == shamir.combine_mnemonics(
        [mnemonics[2][0], mnemonics[2][2], mnemonics[3][0]])
    assert MS == shamir.combine_mnemonics(
        [mnemonics[2][3], mnemonics[3][0], mnemonics[2][4]])

    # One complete group and one incomplete group out of two groups required.
    with pytest.raises(MnemonicError):
        shamir.combine_mnemonics(mnemonics[0][2:] + [mnemonics[1][0]])

    # One group of two required.
    with pytest.raises(MnemonicError):
        shamir.combine_mnemonics(mnemonics[0][1:4])
def test_split_ems():
    identifier = 42
    exponent = 1
    encrypted_master_secret = shamir.encrypt(MS, b"TREZOR", exponent,
                                             identifier)
    mnemonics = shamir.split_ems(1, [(3, 5)], identifier, exponent,
                                 encrypted_master_secret)

    recovered = shamir.combine_mnemonics(mnemonics[0][:3], b"TREZOR")
    assert recovered == MS
Пример #13
0
def test_split_ems():
    identifier = 42
    exponent = 1
    encrypted_master_secret = shamir.EncryptedMasterSecret.from_master_secret(
        MS, b"TREZOR", identifier, exponent)
    grouped_shares = shamir.split_ems(1, [(3, 5)], encrypted_master_secret)
    mnemonics = [share.mnemonic() for share in grouped_shares[0]]

    recovered = shamir.combine_mnemonics(mnemonics[:3], b"TREZOR")
    assert recovered == MS
Пример #14
0
def test_group_sharing_threshold_1():
    group_threshold = 1
    group_sizes = (5, 3, 5, 1)
    member_thresholds = (3, 2, 2, 1)
    mnemonics = shamir.generate_mnemonics(
        group_threshold, list(zip(member_thresholds, group_sizes)), MS)

    # Test all valid combinations of mnemonics.
    for group, threshold in zip(mnemonics, member_thresholds):
        for group_subset in combinations(group, threshold):
            mnemonic_subset = list(group_subset)
            shuffle(mnemonic_subset)
            assert MS == shamir.combine_mnemonics(mnemonic_subset)
Пример #15
0
def combine_mnemonics(m):
    shares = []
    for i in range(m):
        print('\n=========================')
        share = input(f'Enter mnemonic share #{i+1}:\n').strip()
        print('=========================')
        shares.append(share)
    try:
        seed = shamir_mnemonic.combine_mnemonics(shares)
    except shamir_mnemonic.MnemonicError as e:
        print()
        print(e, file=sys.stderr)
        sys.exit(2)
    phrase = seed_to_phrase(seed)
    return seed, phrase
Пример #16
0
def backup_flow_slip39_basic(client):
    mnemonics = []

    def input_flow():
        # 1. Checklist
        # 2. Number of shares (5)
        # 3. Checklist
        # 4. Threshold (3)
        # 5. Checklist
        # 6. Confirm show seeds
        yield from click_through(client.debug, screens=6, code=B.ResetDevice)

        # Mnemonic phrases
        for _ in range(5):
            yield  # Phrase screen
            mnemonic = read_and_confirm_mnemonic(client.debug, words=20)
            mnemonics.append(mnemonic)
            yield  # Confirm continue to next
            client.debug.press_yes()

        # Confirm backup
        yield
        client.debug.press_yes()

    with client:
        client.set_input_flow(input_flow)
        client.set_expected_responses(
            [messages.ButtonRequest(code=B.ResetDevice)] * 6  # intro screens
            + [
                messages.ButtonRequest(code=B.ResetDevice),
                messages.ButtonRequest(code=B.Success),
            ] * 5  # individual shares
            + [
                messages.ButtonRequest(code=B.Success),
                messages.Success(),
                messages.Features(),
            ])
        device.backup(client)

    mnemonics = mnemonics[:3]
    ms = shamir.combine_mnemonics(mnemonics)
    identifier, iteration_exponent, _, _, _ = shamir._decode_mnemonics(
        mnemonics)
    secret = shamir._encrypt(ms, b"", iteration_exponent, identifier)
    return secret
def test_basic_sharing_random():
    secret = secrets.token_bytes(16)
    mnemonics = shamir.generate_mnemonics(1, [(3, 5)], secret)[0]
    assert shamir.combine_mnemonics(mnemonics[:3]) == shamir.combine_mnemonics(
        mnemonics[2:])
def test_backup_slip39_advanced(client):
    assert client.features.needs_backup is True
    mnemonics = []

    def input_flow():
        # 1. Checklist
        # 2. Set and confirm group count
        # 3. Checklist
        # 4. Set and confirm group threshold
        # 5. Checklist
        # 6-15: for each of 5 groups:
        #   1. Set & Confirm number of shares
        #   2. Set & confirm share threshold value
        # 16. Confirm show seeds
        yield from click_through(client.debug, screens=16, code=B.ResetDevice)

        # Mnemonic phrases
        for _ in range(5):
            for _ in range(5):
                yield  # Phrase screen
                mnemonic = read_and_confirm_mnemonic(client.debug, words=20)
                mnemonics.append(mnemonic)
                yield  # Confirm continue to next
                client.debug.press_yes()

        # Confirm backup
        yield
        client.debug.press_yes()

    with client:
        client.set_input_flow(input_flow)
        client.set_expected_responses([
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.ResetDevice),  # group #1 counts
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.ResetDevice),  # group #2 counts
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.ResetDevice),  # group #3 counts
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.ResetDevice),  # group #4 counts
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.ResetDevice),  # group #5 counts
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.ResetDevice),  # show seeds
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),
            messages.ButtonRequest(code=B.ResetDevice),
            messages.ButtonRequest(code=B.Success),  # show seeds ends here
            messages.ButtonRequest(code=B.Success),
            messages.Success(),
        ])
        device.backup(client)

    client.init_device()
    assert client.features.initialized is True
    assert client.features.needs_backup is False
    assert client.features.unfinished_backup is False
    assert client.features.no_backup is False
    assert client.features.backup_type is messages.BackupType.Slip39_Advanced

    expected_ms = shamir.combine_mnemonics(MNEMONIC_SLIP39_ADVANCED_20)
    actual_ms = shamir.combine_mnemonics(mnemonics[:3] + mnemonics[5:8] +
                                         mnemonics[10:13])
    assert expected_ms == actual_ms
Пример #19
0
def combine_shares(shares):
    msg = shamir.combine_mnemonics(shares)
    return msg
Пример #20
0
def test_passphrase():
    mnemonics = shamir.generate_mnemonics(1, [(3, 5)], MS, b"TREZOR")[0]
    assert MS == shamir.combine_mnemonics(mnemonics[1:4], b"TREZOR")
    assert MS != shamir.combine_mnemonics(mnemonics[1:4])
Пример #21
0
def test_basic_sharing_fixed():
    mnemonics = shamir.generate_mnemonics(1, [(3, 5)], MS)[0]
    assert MS == shamir.combine_mnemonics(mnemonics[:3])
    assert MS == shamir.combine_mnemonics(mnemonics[1:4])
    with pytest.raises(MnemonicError):
        shamir.combine_mnemonics(mnemonics[1:3])
Пример #22
0
        addr   = btc.address.for_p2s(script)
    if path[0:2] == "84":
        addr   = btc.address.for_p2pkh_wit(hash)   
    xpub = acct.hwif(as_private=False)
    xprv = acct.hwif(as_private=True)
    print(f"\n{xprv}\n{xpub}\n{addr}")

def main(seed, sss, passphrase):
    print("Passphrase:", f'"{passphrase}"')
    print("Master Seed:", seed.hex())
    print(sss[-1][-1])
    print_keys(seed, ACCT44, None)
    print_keys(seed, ACCT49, HW49)
    print_keys(seed, ACCT84, HW84)

if __name__ == "__main__":
    if len(argv) < 3:
        print(f"Usage:\t{argv[0]}",
              "<passphrase> <master_seed | shamir-mnemonic>")
        print('\tHint: Use "" as your passphrase if you have none')
    else:
        passphrase = argv[1]
        args = " ".join(argv[2:]).replace("0x","").strip()
        if all(c in hexdigits for c in args):
            sss = generate_mnemonics(1, [(1,1)], bytes.fromhex(args),
                                     passphrase.encode(), 0)
        else:
            sss = [[args]]
        seed = combine_mnemonics(sss[-1],passphrase.encode())
        main(seed, sss, passphrase)
Пример #23
0
def test_basic_sharing_random():
    mnemonics = shamir.generate_mnemonics_random(1, [(3, 5)])[0]
    assert shamir.combine_mnemonics(mnemonics[:3]) == shamir.combine_mnemonics(
        mnemonics[2:])
Пример #24
0
# Nonsense Passphrase and Master-Seed
PP     = "Pa55w0rd"
MSEC   = "0660cc198330660cc198330660cc1983" # SLIP-14 entryopy for fun

ACCT44 = '44H/0H/0H'
ACCT49 = '49H/0H/0H'
ACCT84 = '84H/0H/0H'
HW49 = dict(bip32_pub_prefix_hex="049d7cb2", bip32_prv_prefix_hex="049d7878")
HW84 = dict(bip32_pub_prefix_hex="04b24746", bip32_prv_prefix_hex="04b2430c")

# Can be done MS -> shamir-mnemonic or shamir-mnemonic -> MS
SSS  = generate_mnemonics(1, [(1,1)], bytes.fromhex(MSEC), PP.encode(), 0)
#SSS = [["armed husband academic academic document aquatic wisdom " +
#        "pleasure lilac response axle parking shaft crazy cargo " +
#        "dish diet dramatic together unfold"]]
seed = combine_mnemonics(SSS[-1],PP.encode())

print(seed.hex())
print(SSS[-1][-1], "\n")

# BIP44 derivations and xpub/xprv prefix
acct44 = btc.keys.bip32_seed(seed).subkey_for_path(ACCT44)
key44  = acct44.subkey_for_path('0/0')
addr44 = key44.address()
xprv44 = acct44.hwif(as_private=True)
xpub44 = acct44.hwif(as_private=False)
print(xprv44)
print(xpub44)
print(addr44, "\n")

# BIP49 derivations and ypub/yprv prefix
Пример #25
0
def test_backup_slip39_advanced(client, click_info: bool):
    assert client.features.needs_backup is True
    mnemonics = []

    def input_flow():
        yield  # Checklist
        client.debug.press_yes()
        if click_info:
            yield from click_info_button(client.debug)
        yield  # Set and confirm group count
        client.debug.press_yes()
        yield  # Checklist
        client.debug.press_yes()
        if click_info:
            yield from click_info_button(client.debug)
        yield  # Set and confirm group threshold
        client.debug.press_yes()
        yield  # Checklist
        client.debug.press_yes()
        for _ in range(5):  # for each of 5 groups
            if click_info:
                yield from click_info_button(client.debug)
            yield  # Set & Confirm number of shares
            client.debug.press_yes()
            if click_info:
                yield from click_info_button(client.debug)
            yield  # Set & confirm share threshold value
            client.debug.press_yes()
        yield  # Confirm show seeds
        client.debug.press_yes()

        # Mnemonic phrases
        for _ in range(5):
            for _ in range(5):
                # Phrase screen
                mnemonic = yield from read_and_confirm_mnemonic(client.debug)
                mnemonics.append(mnemonic)
                yield  # Confirm continue to next
                client.debug.press_yes()

        yield  # Confirm backup
        client.debug.press_yes()

    with client:
        if click_info:
            client.watch_layout()
        client.set_input_flow(input_flow)
        client.set_expected_responses(
            [messages.ButtonRequest(code=B.ResetDevice)]
            * (8 if click_info else 6)  # intro screens (and optional info)
            + [
                (click_info, messages.ButtonRequest(code=B.ResetDevice)),
                messages.ButtonRequest(code=B.ResetDevice),
                (click_info, messages.ButtonRequest(code=B.ResetDevice)),
                messages.ButtonRequest(code=B.ResetDevice),
            ]
            * 5  # group thresholds (and optional info)
            + [
                messages.ButtonRequest(code=B.ResetDevice),
                messages.ButtonRequest(code=B.Success),
            ]
            * 25  # individual shares
            + [
                messages.ButtonRequest(code=B.Success),
                messages.Success,
                messages.Features,
            ]
        )
        device.backup(client)

    client.init_device()
    assert client.features.initialized is True
    assert client.features.needs_backup is False
    assert client.features.unfinished_backup is False
    assert client.features.no_backup is False
    assert client.features.backup_type is messages.BackupType.Slip39_Advanced

    expected_ms = shamir.combine_mnemonics(MNEMONIC_SLIP39_ADVANCED_20)
    actual_ms = shamir.combine_mnemonics(
        mnemonics[:3] + mnemonics[5:8] + mnemonics[10:13]
    )
    assert expected_ms == actual_ms