From c009218e2933a110abb3b83e2d65de090bf45bd9 Mon Sep 17 00:00:00 2001 From: tochka4 Date: Sat, 5 Jun 2021 00:52:20 +0400 Subject: [PATCH] Added create_mnemonic_additional_share function, fixed embedded index range --- pybtc/functions/bip39_mnemonic.py | 41 +++++++++++++++++++++++++- pybtc/functions/shamir.py | 4 +-- setup.py | 2 +- tests/test_bip39_mnemonic_functions.py | 8 ++++- 4 files changed, 50 insertions(+), 5 deletions(-) diff --git a/pybtc/functions/bip39_mnemonic.py b/pybtc/functions/bip39_mnemonic.py index 9f6379e7..e61a3ff6 100644 --- a/pybtc/functions/bip39_mnemonic.py +++ b/pybtc/functions/bip39_mnemonic.py @@ -199,7 +199,8 @@ def split_mnemonic(mnemonic, threshold, total, language='english', embedded_inde entropy = mnemonic_to_entropy(mnemonic, language=language, hex=False, word_list_dir=word_list_dir, word_list=word_list) if embedded_index: - bits = math.ceil(math.log2(total)) + 1 + bits = math.ceil(len(entropy) * 8 / 32) + # bits = math.ceil(math.log2(total)) + 1 else: bits = 8 shares = split_secret(threshold, total, entropy, bits) @@ -215,6 +216,7 @@ def split_mnemonic(mnemonic, threshold, total, language='english', embedded_inde raise Exception("split secret failed") if embedded_index: result = [] + for share in shares: result.append(entropy_to_mnemonic(shares[share], language=language, word_list_dir=word_list_dir, @@ -228,6 +230,43 @@ def split_mnemonic(mnemonic, threshold, total, language='english', embedded_inde return result +def create_mnemonic_additional_share(threshold_shares, language='english', word_list_dir=None, word_list=None): + embedded_index = isinstance(threshold_shares, list) + s = dict() + if embedded_index: + for share in threshold_shares: + e = mnemonic_to_entropy(share, language=language, hex=False, word_list_dir=word_list_dir, + word_list=word_list) + i = get_mnemonic_checksum_data(share) + if i in s: + raise ValueError("Non unique or invalid shares") + s[i] = e + else: + for share in threshold_shares: + s[share] = mnemonic_to_entropy(threshold_shares[share], language=language, + hex=False, word_list_dir=word_list_dir, word_list=word_list) + if embedded_index: + bits = math.ceil(len(s[next(iter(s))]) * 8 / 32) + index_max = 2 ** bits - 1 + assert index_max > len(threshold_shares) + else: + index_max = 255 + + while True: + q = random.SystemRandom().randint(1, index_max) + if q in s: + continue + break + entropy = restore_secret(s, x = q) + + if embedded_index: + return entropy_to_mnemonic(entropy, language=language, word_list_dir=word_list_dir, + data=q, word_list=word_list) + else: + return q, entropy_to_mnemonic(entropy, language=language, word_list_dir=word_list_dir, word_list=word_list) + + + def combine_mnemonic(shares, language='english', word_list_dir=None, word_list=None): embedded_index = isinstance(shares, list) s = dict() diff --git a/pybtc/functions/shamir.py b/pybtc/functions/shamir.py index 0454e47b..26f9a451 100644 --- a/pybtc/functions/shamir.py +++ b/pybtc/functions/shamir.py @@ -121,7 +121,7 @@ def split_secret(threshold, total, secret, index_bits=8): return shares -def restore_secret(shares): +def restore_secret(shares, x=0): secret = b"" share_length = None for share in shares: @@ -134,5 +134,5 @@ def restore_secret(shares): raise Exception("Invalid shares") for i in range(share_length): - secret += bytes([_interpolation([(z, shares[z][i]) for z in shares])]) + secret += bytes([_interpolation([(z, shares[z][i]) for z in shares], x=x)]) return secret diff --git a/setup.py b/setup.py index 5af3ba68..6610d8a4 100644 --- a/setup.py +++ b/setup.py @@ -122,7 +122,7 @@ def run(self): return _build_ext.run(self) setup(name='pybtc', - version='2.3.8', + version='2.3.9', description='Python Bitcoin library', keywords='bitcoin', url='https://github.com/bitaps-com/pybtc', diff --git a/tests/test_bip39_mnemonic_functions.py b/tests/test_bip39_mnemonic_functions.py index 08c96102..f1d0f4ac 100644 --- a/tests/test_bip39_mnemonic_functions.py +++ b/tests/test_bip39_mnemonic_functions.py @@ -8,6 +8,7 @@ from pybtc.functions.bip39_mnemonic import is_mnemonic_checksum_valid from pybtc.functions.bip39_mnemonic import split_mnemonic from pybtc.functions.bip39_mnemonic import combine_mnemonic +from pybtc.functions.bip39_mnemonic import create_mnemonic_additional_share def test_generate_entropy(): assert len(generate_entropy()) == 64 @@ -135,4 +136,9 @@ def test_split_mnemonic(): "wagon unique pilot subject cactus behave tide"] assert combine_mnemonic(shares) == "enforce north frost swear trial burst girl soccer rent town sea express other " \ - "oblige insect youth swarm violin stable push twin close clump extra" \ No newline at end of file + "oblige insect youth swarm violin stable push twin close clump extra" + shares = ["occur hazard mail question wisdom pill grass tackle fit nephew gown motion", + "embark fold seat fix quiz pull fortune wagon clever staff analyst symptom"] + s = create_mnemonic_additional_share(shares) + + assert combine_mnemonic(shares) == combine_mnemonic([shares[0], s])