def _recover_secret(threshold: int, shares: List[Tuple[int, bytes]]) -> bytes: # If the threshold is 1, then the digest of the shared secret is not used. if threshold == 1: return shares[0][1] shared_secret = shamir.interpolate(shares, _SECRET_INDEX) digest_share = shamir.interpolate(shares, _DIGEST_INDEX) digest = digest_share[:_DIGEST_LENGTH_BYTES] random_part = digest_share[_DIGEST_LENGTH_BYTES:] if digest != _create_digest(random_part, shared_secret): raise MnemonicError("Invalid digest of the shared secret.") return shared_secret
def _split_secret( threshold: int, share_count: int, shared_secret: bytes ) -> List[Tuple[int, bytes]]: if threshold < 1: raise ValueError( "The requested threshold ({}) must be a positive integer.".format(threshold) ) if threshold > share_count: raise ValueError( "The requested threshold ({}) must not exceed the number of shares ({}).".format( threshold, share_count ) ) if share_count > MAX_SHARE_COUNT: raise ValueError( "The requested number of shares ({}) must not exceed {}.".format( share_count, MAX_SHARE_COUNT ) ) # If the threshold is 1, then the digest of the shared secret is not used. if threshold == 1: return [(i, shared_secret) for i in range(share_count)] random_share_count = threshold - 2 shares = [(i, random.bytes(len(shared_secret))) for i in range(random_share_count)] random_part = random.bytes(len(shared_secret) - _DIGEST_LENGTH_BYTES) digest = _create_digest(random_part, shared_secret) base_shares = shares + [ (_DIGEST_INDEX, digest + random_part), (_SECRET_INDEX, shared_secret), ] for i in range(random_share_count, share_count): shares.append((i, shamir.interpolate(base_shares, i))) return shares