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
Exemple #11
0
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
Exemple #13
0
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