def test_reconstruct(original_function, original_shares, random_message, setup_name, thresholds): print("\nCalling reconstruct('{}', number_of_people={}, " "random_subset=True, subset={{}}, print_statements=False):".format( setup_name, thresholds[-1])) try: secret, resulting_function, original_determinant, other_determinants, matrix \ = reconstruct(setup_name, thresholds[-1], print_statements=print_statements) except TypeError as e: print( "Could not reconstruct to a valid integer-result (test_setups): {}" .format(e)) sys.exit(1) if not secret == random_message: print( "Reconstruction in setup {} calculated an incorrect result (should be {} but was {})" .format(setup_name, random_message, secret)) sys.exit(1) else: print("The reconstructed function is\t{}, the message is\t{}\n\t" "(Original function was\t{} with secret\t{})".format( print_function(resulting_function, printed=False), secret, print_function(original_function, printed=False), random_message)) print("\nOriginal shares were:") for each_share in original_shares: print(each_share, ":", original_shares[each_share]) return original_determinant, other_determinants
def print_renew_results(new_function, new_result, rec_function, resulting_shares): print("\nThe resulting new shares for the given structure are:") for share in resulting_shares: print("{} : {}".format(share, resulting_shares[share])) print( "Old shares reconstruct the following polynomial:\t\t {}\n" "New generated shares reconstruct the following polynomial:\t {}\n" "New Shares give the same result as old shares ({}), renewal successful." .format(print_function(rec_function, printed=False), print_function(new_function, printed=False), new_result))
def create_random_renew_functions(degree_of_function, field_size, print_statements, shareholders): if print_statements: print("Creating random functions with degree {} and free coefficient 0 for old shareholders." .format(degree_of_function)) # new dict to store all shareholder: function pairs function_dict = {} for old_shareholder in shareholders: function_dict[old_shareholder] = generate_function(degree_of_function, 0, field_size) # print the functions to screen if print_statements: for sh in function_dict: print(sh, ": ", end='') print_function(function_dict[sh]) print("Calculating values for new shareholders from functions") return function_dict
def compute_polynomial(x_values, y_values, k, field_size, print_statements): polynomials = [] for l in range(len(x_values)): l_polynomial = [] for j in range(k): l_k_n = 1 equation = [] # m: iteration index for m in range(k): # j: index for this specific lagrange coefficient if m != j: # p = divide(x - int(x_values[m]), int(x_values[j]) - int(x_values[m]), field_size) % field_size divisor = divide(1, int(x_values[j]) - int(x_values[m]), field_size) equation.append(([divisor, 1], [(- int(x_values[m]) * divisor) % field_size, 0])) # print("EQ:", equation) # print("EQ:", equation) try: tmp = equation[0] # print(tmp) for tup in range(1, k-1): tmp = multiply(tmp, equation[tup], field_size) tmp = [[(tmp[i][0] * y_values[j]) % field_size, tmp[i][1]] for i in range(len(tmp))] # print(tmp) l_polynomial.append(tmp) # print("-->", l_polynomial) except IndexError: return -1 polynomial = sum_polynomials(l_polynomial, field_size) if print_statements: print("Reconstructed polynomial:", print_function(polynomial, False)) return polynomial
def create_random_reset_functions(field_size, k_prime, print_statements, shareholder_shares): if print_statements: print("Creating random functions with degree {} and free coefficient share_value for old shareholders." .format(k_prime - 1)) # new dict to store all shareholder: function pairs function_dict = {} for old_shareholder in shareholder_shares: function_dict[old_shareholder] = \ generate_function(k_prime - 1, shareholder_shares[old_shareholder], field_size) # print the functions to screen if print_statements: for sh in function_dict: print(sh, ": ", end='') print_function(function_dict[sh]) print("Calculating values for new shareholders from functions") return function_dict
def main(): field_size = 997 with open("shamir_setups.yaml", 'r') as stream: try: docs = yaml.load_all(stream) except yaml.YAMLError as exc: print(exc) sys.exit(1) for doc in docs: print("\n{}\n".format(doc)) delete_setup(doc['setup'], hierarchical=False) setup = doc['setup'] info = setup.split(',') minimum_number_of_shares = int(info[0]) number_of_people = int(info[1]) random_message = random.randint(0, field_size - 1) secret, polynomial, shares = make_random_shares(minimum_number_of_shares=minimum_number_of_shares, number_of_people=number_of_people, message=random_message, field_size=field_size) print("Setup", setup) print('secret:\t\t\t', secret) print('shares:', shares) print("f(x) =", print_function(polynomial, False)) reconstructed, reconstructed_polynomial = reconstruct(setup, shares, field_size) print('secret recovered:\t', reconstructed) assert (reconstructed == random_message), "Incorrect reconstruction" print("Reconstruction successful\n") # renew print("renew") _, renew_result = shamir_renew(setup) assert (renew_result == random_message), "Incorrect reconstruction" print("Renew successful\n") # add print("add") _, add_shares = shamir_add(setup, shares, number_of_people+1, field_size) minimum_add_shares = choose_random_subset(add_shares, minimum_number_of_shares) print("Subset for reconstruction: ", minimum_add_shares) add_result, _ = reconstruct(setup, minimum_add_shares, field_size) assert (add_result == random_message), "Incorrect reconstruction, {} != message {}"\ .format(add_result, random_message) print("Add successful\n") # reset print("reset") reset_shares, _ = shamir_reset(setup, "{},{}".format(minimum_number_of_shares, number_of_people*2)) print("Reset successful\n") print("="*211, "\n\n") shares_of_messages_for_multiply, _, _ = create_shares_for_messages(setup, 4, 7, hierarchical=False) success = multiply(setup, shares_of_messages_for_multiply, print_statements=False) if success: print("Multiply successful.") print("*"*211, "\n\n")
def calculate_shares(coefficients, field_size, list_of_people_per_level, print_statements, thresholds, conjunctive): derivatives = calc_derivative_vector(coefficients, (thresholds[-1] - 1), field_size) t = thresholds[-1] # create a dict of shareholder:value pairs share_dict = {} # needed to check if the function needs to be derived old_j = 0 person_number = 1 for level, number in enumerate(list_of_people_per_level): # we need to derive only if we calculate values for a new level j = int(thresholds[level]) # for the disjunctive setup, we don't need t_-1 = 0 -> skip j_disjunctive = int(thresholds[level + 1]) while j > old_j: # if threshold is bigger than current j, we need to derive n times # to get the correct derivative to work with old_j += 1 if print_statements and conjunctive: print("The {}. derivative of the function is \t{}".format( old_j, print_function(derivatives[old_j], printed=False))) if conjunctive: current_function = derivatives[j] else: current_function = derivatives[t - j_disjunctive] # calculate values and append to the share_dict dict for each shareholder for person in range(1, int(number) + 1): if conjunctive: shareholder = ("s_{}_{}".format(person_number, thresholds[level])) else: shareholder = ("s_{}_{}".format( person_number, thresholds[-1] - thresholds[level + 1])) if person == 1 and print_statements and conjunctive: print( "With this function we calculate shares for the following shareholders:" ) # calculate the value for the shareholder result = calc_function(current_function, person_number, field_size) person_number += 1 if print_statements: print("Shareholder {}'s share is {}".format( shareholder, result)) share_dict[shareholder] = result return share_dict
def pre_mult(setup, print_statements=True): field_size, r, shareholders, degree_of_function, k, n = get_setup_info(setup) # first step: choose alpha and beta shares_of_alpha, shares_of_beta, shares_of_r, shares_of_r_star, s_alpha, s_beta =\ call_and_apply_rand_shares(k, field_size, r, shareholders) ''' shares_of_alpha = {1: 12, 2: 17, 3: 22, 4: 27} shares_of_beta = {1: 14, 2: 19, 3: 24, 4: 29} shares_of_r = {1: 17, 2: 25, 3: 33, 4: 41} shares_of_r_star = {1: 16, 2: 46, 3: 108, 4: 214} s_alpha = 7 s_beta = 9 ''' if print_statements: print("[alpha]", shares_of_alpha, "\n", "[beta]", shares_of_beta, "\n", "[r]", shares_of_r, "\n", "[R]", shares_of_r_star) shares_of_d = {} for (i, _) in shareholders: shares_of_d[i] = (((shares_of_alpha[i] * shares_of_beta[i]) % field_size) + shares_of_r_star[i]) % field_size # print(shares_of_d[i], "=", shares_of_alpha[i], "*", shares_of_beta[i], "+", shares_of_r_star[i]) # reconstruct d with access structure (2k, n) d, p = reconstruct("{},{}".format(k*2, n), shares_of_d, field_size) shares_of_gamma = {} for (i, _) in shareholders: shares_of_gamma[i] = (d - shares_of_r[i]) % field_size if print_statements: print(shares_of_gamma[i], "=", d, "-", shares_of_r[i]) g, poly = reconstruct(setup, shares_of_gamma, field_size) if print_statements: print("Reconstructed gamma:", g, "Polynomial:", print_function(poly, False)) assert (s_alpha * s_beta) % field_size == g, "{}*{} (={}) != {}".format(s_alpha, s_beta, (s_alpha * s_beta) % field_size, g) if print_statements: print("Successfully created alpha, beta and gamma values") triples = {} for id in shares_of_alpha: triples[id] = (shares_of_alpha[id], shares_of_beta[id], shares_of_gamma[id]) if print_statements: print(triples) return triples, s_alpha, s_beta
def share(setup, message, field_size=997, name="", print_statements=True): file_path = os.path.join(data_path, setup, 'level_stats.csv') # make sure number is in finite field if message > field_size: old_message = message message = message % field_size print( "Due to the size of the finite field ({}), the secret was changed to {} ({} % {}).\n" .format(field_size, message, old_message, field_size)) list_of_people_per_level, thresholds, conjunctive = \ get_data_and_catch_exceptions(setup, field_size, file_path, message) print(list_of_people_per_level, thresholds, conjunctive) # for conjunctive setup, get the maximum degree of the function to generate degree_of_function = thresholds[-1] - 1 # generate random coefficients c for 0 < c <= prime and a function of those if conjunctive: if print_statements: print("Calculating shares for conjunctive setup") coefficients = generate_function(degree_of_function, message, field_size) else: coefficients = generate_function(degree_of_function, np.random.randint(0, field_size), field_size) print(coefficients) coefficients[-1][0] = message print(coefficients) if print_statements: print("Calculating shares for disjunctive setup") original_function = copy.deepcopy(coefficients) print("The randomly generated function is \t{}".format( print_function(coefficients, False))) # calculate the shares for each shareholder share_dict = calculate_shares(coefficients, field_size, list_of_people_per_level, print_statements, thresholds, conjunctive) if print_statements: # print the dict to the screen print("New shares are: {}".format(share_dict)) # write Shares to 'shares.csv' and save it in the setups directory try: if name: write_shares( field_size, os.path.join(data_path, setup, "shares_{}.csv".format(name)), share_dict) print( "Shares are saved to folder 'DATA/{}/shares_{}.csv'. Please don't edit the csv file manually." .format(setup, name)) else: write_shares(field_size, os.path.join(data_path, setup, "shares.csv"), share_dict) print( "Shares are saved to folder 'DATA/{}/shares.csv'. Please don't edit the csv file manually." .format(setup)) # error handling except PermissionError as e: print( "Can't write to '{}', maybe try to close the file and try again. \n {}" .format(file_path, repr(e))) raise return original_function, share_dict
def renew(setup, old_shares, reset_version_number=None, print_statements=True): # if old shares == {'shares': 'all'} use all shares from the setup; special case for convenience if old_shares == {'shares': 'all'}: old_shares = get_all_shares_from_setup(setup, reset_version_number) new_shares = list(old_shares.keys()) # get all necessary data, i.e. the maximum degree of the functions and the size of the finite field data, degree_of_function, field_size, number_of_old_shares, thresholds = get_all_data_renew( old_shares, reset_version_number, setup) # check if the old shares can reconstruct the correct secret and if all given shareholders actually exist try: rec_result, rec_function, _, _, _ = reconstruct(setup, number_of_old_shares, random_subset=False, subset=old_shares, print_statements=False) except TypeError: print( "Could not reconstruct from old shares, thus no authorised subset is given." ) raise # convert dict of subset to list shares = dict_to_list(old_shares) # troubleshooting check_and_print_validity(data, field_size, new_shares, print_statements, rec_function, rec_result, shares) # start renew by creating random functions of degree thresholds[-1] - 1, with 0 as the free coefficient if print_statements: print( "Creating random functions with degree {} and free coefficient 0 for old shareholders." .format(degree_of_function)) # new dict to store all shareholder: function pairs function_dict = {} for old_shareholder in old_shares: function_dict[old_shareholder] = generate_function( degree_of_function, 0, field_size) # print the functions to screen if print_statements: for sh in function_dict: print(sh, ": ", end='') print_function(function_dict[sh]) print("Calculating values for new shareholders from functions") # create a matrix to store the values calculated in the renew partial_shares = np.zeros((number_of_old_shares + 1, len(new_shares))) # sanity check, should never cause problems assert (len(partial_shares) == len(partial_shares[0]) + 1), 'Wrong format of the matrix of partial results ' \ 'for the new share values.' # write the old share values to the first row of the matrix write_old_share_values(old_shares, partial_shares) # calculate the other values with the formula from the paper # ( f^(j)_(k)(i) for all new shareholders (i,j) for all k) compute_and_add_results(field_size, function_dict, new_shares, partial_shares, thresholds) # calculate the sums of all column values in the matrix sums = sum_over_subshares(field_size, new_shares, partial_shares, print_statements) # save the newly calculated values in a new shareholder:share dict resulting_shares = {} for i in range(len(sums)): resulting_shares[new_shares[i]] = int(sums[i]) # check if the new shares produce the same result in the reconstruction as the old ones new_result, new_function, _, _, _ = reconstruct(setup, random_subset=False, subset=resulting_shares, print_statements=False) # if not, raise an error if not (new_result == rec_result): raise ValueError("New Shares don't produce the same result ({}) " "as old shares ({}).".format(new_result, rec_result)) elif print_statements: # print all calculated information to the screen print_renew_results(new_function, new_result, rec_function, resulting_shares) # create new .csv file to store the information file_path = create_renew_file(field_size, resulting_shares, setup) if print_statements: print("New Shares are saved to {}".format(file_path)) return resulting_shares, new_result
def reconstruct_linear(setup, number_of_people=0, random_subset=True, subset=empty_dict, reset_version_number=None, print_statements=True): # if none of the default values is given, return with error if number_of_people == 0 and random_subset is True and subset == empty_dict: raise Exception( "Please enter either a correct subset of shareholders for 'subset='" "while setting random_subset=False or set random_subset=True" "and provide a number_of_people you want to reconstruct the secret from." ) # create placeholders for a list of shares, of person IDs and functions shares = [] person_ids = [] functions_involved = [] # read all necessary data from the setup try: data, _, thresholds = read_data(setup, reset_version_number) conjunctive = read_sharing_type(setup) except FileNotFoundError as e: print("Could not find file:\n{}".format(repr(e))) return # get size of finite field field_size = read_field_size(setup) # read data of shareholders into tuples tuples = [tuple(x) for x in data.values] # if chosen, select a random sample of given shareholders if random_subset: try: share_list = random.sample(tuples, number_of_people) except ValueError as e: print( "More people chosen ({}) than existing, please choose at most {} shareholders.\n{}" .format(number_of_people, len(tuples), repr(e))) raise # else use given subset else: # catch case subset == {} if not subset: raise Exception( "Please enter a valid Dictionary of (shareholder:share) pairs as subset\n" 'Example: subset={"s_0_0": 13, "s_1_0": 11}') # read dict of subset into a list of lists share_list = dict_to_list(subset) number_of_people = len(share_list) if print_statements: print("All given shareholders: {}".format(tuples)) print("Subset of {} shareholders randomly selected is {}.".format( number_of_people, share_list)) # expand the lists of shares and person IDs for i, shareholder in enumerate(share_list): name = shareholder[0].split('_') name = name[1:] try: shares.append(int(shareholder[1])) person_ids.append((int(name[0]), int(name[1]))) # handling errors except ValueError as e: print( "Wrong format of shareholders given, should be 's_i_j' for ID (i,j)\n{}" .format(repr(e))) raise except IndexError as e: print( "Wrong format of shareholders given, should be 's_i_j' for ID (i,j)\n{}" .format(repr(e))) raise # sort person IDs and corresponding shares into lexicographic order person_ids, shares = sort_coordinates(person_ids, shares) if print_statements: print("Coordinates (in lexicographic order) are {}".format(person_ids)) # read all involved functions (phi) for i in range(thresholds[-1]): functions_involved.append(i) phi = functions_involved if print_statements: print( "Share value column for interpolation (in lexicographic order) is {}" .format(shares)) print("Vector phi of function x^i (with i printed) is {}".format(phi)) # create an interpolation matrix E and read highest i and j for simplicity matrix, max_person_number, highest_derivative = interpolation_matrix( person_ids) if print_statements: print("The interpolation matrix is \n {}".format(matrix)) print("\nChecking thresholds and requirements:") # check preliminaries for the interpolation if not thresholds_fulfilled(setup, person_ids, print_statements, conjunctive): raise ThresholdNotFulfilledException if not requirement_1(matrix, highest_derivative, max_person_number): print( "Requirement 1 'Unique Solution' not satisfied with given subset.") raise RequirementNotFulfilledException elif print_statements: print("Requirement 1 'Unique Solution' is satisfied.") if supported_sequence(matrix): print( "Requirement 1 'No supported 1-sequence of odd length' not satisfied with given subset." ) raise RequirementNotFulfilledException elif print_statements: print( "Requirement 1 'No supported 1-sequence of odd length' is satisfied." ) if not requirement_2(highest_derivative, field_size, max_person_number): pass # TODO figure x_k out for precondition 2; FULFILLMENT OF REQUIREMENT 2 NOT IMPLEMENTED ''' print("Requirement 2 'Unique solution over finite field of size {}'" "not satisfied with given subset.".format(field_size)) return ''' elif print_statements: print( "Requirement 2 'Unique solution over finite field of size {}' is satisfied." .format(field_size)) # create a matrix with the linear equations to solve A = create_matrix(person_ids, shares, field_size, phi, highest_derivative) if print_statements: print( "\nAll requirements for a unique solution are given, starting interpolation..." ) print("\nResulting matrix of linear equations is:", end='') print_matrix(A) try: # solve the linear equations to get the coefficients resulting_matrix, coefficients = gauss_jordan(A, field_size) if print_statements: print( "Using Gauss-Jordan elimination to get the coefficients of the function..." ) print("Resulting matrix is:", end='') print_matrix(A) except ValueError as e: print(e) raise except RuntimeWarning as e: print(e) raise # sanity check, we might encounter an overdetermined system, check that all equations not worked on equal zero # or alternatively are just a copy of the line holding the result; this way the result is also right sanity_coefficients = list(coefficients[len(A[0]) - 1:]) for position, c in enumerate(sanity_coefficients): if not c[0] == 0: # catch the second case from above (just a copied line) if not equal(resulting_matrix[c[1]], resulting_matrix[len(A[0]) - 2]): raise ValueError( "Error in Calculation, Gauss-Jordan elimination could not produce a correct result" ) # print the final function and the secret final_coefficients = list(coefficients[:len(A[0])]) print(final_coefficients) if conjunctive: secret = int(final_coefficients[0][0]) else: # input leads to an overdetermined system of equations, (one more) # thus the last equation will be 0 and the secret is in the second to last equation secret = int(final_coefficients[-2][0]) if print_statements: print( "Reading coefficients from interpolated function from the matrix..." ) print("The interpolated function is \t", end='') reconstructed_function = print_function(final_coefficients) print("The secret is {}".format(secret)) print("\nReconstruction finished.") else: reconstructed_function = print_function(final_coefficients, printed=False) return secret, reconstructed_function
def reconstruct(setup, number_of_people=0, random_subset=True, subset=empty_dict, reset_version_number=None, print_statements=True, test=False): # if none of the default values is given, return with error if number_of_people == 0 and random_subset is True and subset == empty_dict: raise ValueError( "Please enter either a correct subset of shareholders for 'subset='" "while setting random_subset=False or set random_subset=True" "and provide a number_of_people you want to reconstruct the secret from." ) # create placeholders for a list of shares, of person IDs and functions functions_involved = [] # read all necessary data from the setup field_size, thresholds, tuples, conjunctive = get_needed_data_reconstruct( reset_version_number, setup) number_of_people, share_list = select_subset_of_shareholders( number_of_people, random_subset, subset, tuples) if print_statements: print("All given shareholders: {}".format(tuples)) print("Subset of {} shareholders selected is {}.".format( number_of_people, share_list)) # get and sort the coordinates (IDs) of all shareholders and their according shares # also get all involved phi-values person_ids, phi, shares = extract_coordinates_and_phis( functions_involved, print_statements, share_list, thresholds) # leads to a non-square matrix if conjunctive and not len(person_ids) == len(phi): raise ValueError( "\nMatrix A is of format {}x{} but must be square for determinant calculation. " "(You need exactly {} shareholders to reconstruct)".format( len(person_ids), len(phi), len(phi))) if print_statements: print( "Share value column for interpolation (in lexicographic order) is {}" .format(shares)) print("Vector phi of function x^i (with i printed) is {}".format(phi)) # create an interpolation matrix E and read highest i and j for simplicity matrix, max_person_number, highest_derivative = interpolation_matrix( person_ids) if print_statements: print("The interpolation matrix is \n {}".format(matrix)) print("\nChecking thresholds and requirements:") # check preliminaries for the interpolation check_requirements(conjunctive, field_size, highest_derivative, matrix, max_person_number, person_ids, print_statements, setup) # create a matrix with the linear equations to solve if print_statements: print( "\nAll requirements for a unique solution are given, starting interpolation..." ) # calculate matrix A from the paper a_matrix = calculate_a_matrix(person_ids, phi, int(field_size)) if not test: matrix_path = os.path.join(data_path, setup, 'matrix_A.txt') # save the matrix to the bulletin board np.savetxt(matrix_path, a_matrix, fmt='%d') if print_statements: print("Calculated matrix A(E, X, phi) =", end='') print_matrix(a_matrix) det, determinants, resulting_function = apply_birkhoff_reconstruction( a_matrix, field_size, print_statements, shares) if print_statements: print("The reconstructed function is\n{}".format( print_function(resulting_function, printed=False))) # secret message is the free coefficient if conjunctive: secret = resulting_function[0][0] if not conjunctive: secret = resulting_function[-1][0] if print_statements: print("The reconstructed message is {}\n\n".format(secret)) return secret, resulting_function, det, determinants, a_matrix
def reset(setup, old_shares, new_shares=new_list, create_new_shares_randomly=False, number_of_random_shares=0, reset_version_number=None, print_statements=True): # read field size and level structure from data data, field_size, level_structure, thresholds, conjunctive = get_all_data_reset( new_shares, reset_version_number, setup) degree_of_function, new_shares, number_of_old_shares = set_up_new_shares( create_new_shares_randomly, new_shares, number_of_random_shares, old_shares, thresholds) old_degree_of_function = thresholds[-1] - 1 # troubleshooting if not new_shares: raise ValueError( "Please enter a valid set of new shareholders " "(or a number >0 if you want to create random new shares).") # get results from reconstruction with old shares, most of it used for console outputs and verification rec_result, rec_function, determinant_of_original_matrix, determinants, _ =\ reconstruct(setup, number_of_old_shares, random_subset=False, subset=old_shares, print_statements=False) matrix_path = os.path.join(data_path, setup, 'matrix_A.txt') # load matrix A for calculation of birkhoff coefficients matrix = np.loadtxt(matrix_path, dtype=int) # put the dict of old shares into list format shares = dict_to_list(old_shares) # check if all given shareholders exist check_for_errors_and_print_results(data, degree_of_function, field_size, new_shares, old_shares, print_statements, rec_result, shares) # get two lists of shareholder IDs and share values old_shares_list = dict_to_list(old_shares) person_ids, shares = shareholder_share_list_to_lists(old_shares_list) # put those lists into lexicographic order person_ids, vector_of_shares = sort_coordinates(person_ids, shares) # actual reset starts here # dictionary of random functions for each old shareholder function_dict = {} if debug: print("\nStep 1: calculate Birkhoff Coefficients") # i == l-1 if conjunctive: compute_birkhoff_coefficients_and_polynomials( degree_of_function, determinant_of_original_matrix, field_size, function_dict, matrix, person_ids, print_statements, vector_of_shares) else: compute_birkhoff_coefficients_and_polynomials_disjunctive( degree_of_function, determinant_of_original_matrix, field_size, function_dict, matrix, person_ids, print_statements, vector_of_shares, old_degree_of_function) if debug: print("\nStep 2: Calculated functions with random coefficients") for sh in function_dict: print(sh, ":", function_dict[sh]) print("\nStep 3: compute subshares for new shareholders") partial_shares = np.zeros((number_of_old_shares, len(new_shares))) compute_subshares_for_other_shareholders(field_size, function_dict, level_structure, new_shares, partial_shares) if debug: print_matrix(partial_shares) # sum up all columns and % field_size sums = sum_over_subshares(field_size, new_shares, partial_shares, print_statements) resulting_shares = {} # assign each new shareholder its final result from the summed column for i in range(len(sums)): resulting_shares[new_shares[i]] = int(sums[i]) # create a new reset each time and give them a unique number file_path, number_of_reset = create_reset_file(field_size, level_structure, resulting_shares, setup) if print_statements or debug: print("The resulting new shares for the given structure are:\n{}" "\nNew Shares are saved to {}".format(resulting_shares, file_path)) new_result, new_function, _, _, _ = reconstruct( setup, random_subset=False, subset=resulting_shares, reset_version_number=number_of_reset, print_statements=False) if not (new_result == rec_result): raise ValueError( "In Reset: New Shares for '{}' don't produce the same result ({}) " "as old shares ({}).".format(setup, new_result, rec_result)) elif print_statements: print( "Reconstructed function for old Shareholders is {}\n" "Reconstructed function for reset shareholders is {}\n" "New Shares give the same result as old shares ({}), reset successful." .format(print_function(rec_function, False), print_function(new_function, False), new_result)) return resulting_shares