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])
Example #2
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
def test_all_groups_exist():
    for threshold in (1, 2, 5):
        mnemonics = shamir.generate_mnemonics(threshold,
                                              [(3, 5), (1, 1), (2, 3), (2, 5),
                                               (3, 5)], MS)
        assert len(mnemonics) == 5
        assert len(sum(mnemonics, [])) == 19
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])
Example #5
0
def test_recover_ems():
    mnemonics = shamir.generate_mnemonics(1, [(3, 5)], MS, b"TREZOR")[0]

    groups = shamir.decode_mnemonics(mnemonics[:3])
    encrypted_master_secret = shamir.recover_ems(groups)
    recovered = encrypted_master_secret.decrypt(b"TREZOR")
    assert recovered == MS
def test_recover_ems():
    mnemonics = shamir.generate_mnemonics(1, [(3, 5)], MS, b"TREZOR")[0]

    identifier, exponent, encrypted_master_secret = shamir.recover_ems(
        mnemonics[:3])
    recovered = shamir.decrypt(encrypted_master_secret, b"TREZOR", exponent,
                               identifier)
    assert recovered == MS
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)
def test_invalid_sharing():
    # Short master secret.
    with pytest.raises(ValueError):
        shamir.generate_mnemonics(1, [(2, 3)], MS[:14])

    # Odd length master secret.
    with pytest.raises(ValueError):
        shamir.generate_mnemonics(1, [(2, 3)], MS + b"X")

    # Group threshold exceeds number of groups.
    with pytest.raises(ValueError):
        shamir.generate_mnemonics(3, [(3, 5), (2, 5)], MS)

    # Invalid group threshold.
    with pytest.raises(ValueError):
        shamir.generate_mnemonics(0, [(3, 5), (2, 5)], MS)

    # Member threshold exceeds number of members.
    with pytest.raises(ValueError):
        shamir.generate_mnemonics(2, [(3, 2), (2, 5)], MS)

    # Invalid member threshold.
    with pytest.raises(ValueError):
        shamir.generate_mnemonics(2, [(0, 2), (2, 5)], MS)

    # Group with multiple members and threshold 1.
    with pytest.raises(ValueError):
        shamir.generate_mnemonics(2, [(3, 5), (1, 3), (2, 5)], MS)
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])
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])
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:])
    output.i += 1
    output.data.append(("{}. {}".format(output.i, description), mnemonics, secret.hex()))


output.i = 0
output.data = []

shamir.RANDOM_BYTES = random_bytes

if __name__ == "__main__":
    random.seed(1337)

    for n in [16, 32]:
        description = "Valid mnemonic without sharing ({} bits)"
        secret = random_bytes(n)
        groups = shamir.generate_mnemonics(1, [(1, 1)], secret, b"TREZOR")
        output(description.format(8 * n), groups[0], secret)

        description = "Mnemonic with invalid checksum ({} bits)"
        indices = list(shamir.mnemonic_to_indices(groups[0][0]))
        indices[-1] ^= 1
        mnemonic = shamir.mnemonic_from_indices(indices)
        output(description.format(8 * n), [mnemonic], b"")

        description = "Mnemonic with invalid padding ({} bits)"
        overflowing_bits = (8 * n) % shamir.RADIX_BITS
        if overflowing_bits:
            indices = list(shamir.mnemonic_to_indices(groups[0][0]))
            indices[4] += 1 << overflowing_bits
            indices = tuple(indices[: -shamir.CHECKSUM_LENGTH_WORDS])
            mnemonic = shamir.mnemonic_from_indices(
Example #13
0
from pycoin.symbols.btc import network as btc
from pycoin.networks.bitcoinish import create_bitcoinish_network as btcnet
from shamir_mnemonic import combine_mnemonics, generate_mnemonics

# 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)
Example #14
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)
Example #15
0
def create_shares(secret):
    #secret = secrets.token_bytes(16)
    #secret = secret.encode('utf-8')
    shares = shamir.generate_mnemonics(1, [(3, 6)], secret)[0]
    return shares