def collude_and_recover(num_players, reconstruction_threshold, max_secret_length, shares_subset, num_collude):
    '''
    Args:
        num_players, the number of players that were shared across
        reconstruction_threshold, the threshold for reconstruction
        max_secret_length, the maximum length of the secret that was shared
        shares_subset, a dictionary of a subset of players to json robust shares
        num_corrupt, the number of players that will collude
    Returns:
        the result of robust reconstruction
    '''
    max_secret_length = len(secret)

    colluders = {player: rss._deserialize_robust_share(share) for player, share in shares_subset.items()[:num_collude]}

    for player, player_dict in colluders.items():
        player_dict["share"] /= 2
        for verifier, verifier_dict in colluders.items():
            new_key, new_vector = authentication.generate_check_vector(player_dict["share"], max_secret_length)
            verifier_dict["keys"][player] = new_key
            player_dict["vectors"][verifier] = new_vector

    # assert that these players do in fact collude
    for verifier, verifier_dict in colluders.items():
        for player, player_dict in colluders.items():
            assert authentication.validate(verifier_dict["keys"][player], player_dict["vectors"][verifier],
                                           player_dict["share"], max_secret_length) is True

    shares = combine_testing_dictionaries(shares_subset, jsonify_dict(colluders))
    return rss.reconstruct_authenticated_secret(num_players, reconstruction_threshold, max_secret_length, shares)
Esempio n. 2
0
def reconstruct(shares_map, secret_length, total_shares, threshold):
    """
    Reconstruct a secret if possible from the given shares.
    If the shares are corrupt or the given number of shares is less than the
    recreation threshold, invalid data will be returned.

    Args:
        shares_map: a map of player_id to the share assigned to that player in call to share
        secret_length: the length of the secret that was shared
        total_shares: the original number of shares created
        threshold: the number of shares required to reconstruct the secret.
    Returns:
        If successful
        (secret, honest_players, dishonest_players)
        secret: the original bytestring that was shared by share_authenticated_secret
        honest_players: a non-exhaustive list of players whose shares could be used for reconstruction of that secret
        dishonest_players: a non-exhaustive list of dishonest players (specifically those whose shares caused structural errors)
    Raises:
        ReconstructionError: the underlying library could not reconstruct
        LibraryException: an exception was thrown by the supporting sharing library
    """
    try:
        return rss.reconstruct_authenticated_secret(total_shares, threshold, secret_length, shares_map)
    except rss.FatalReconstructionFailure:
        logging.exception("Exception encountered during secret share reconstruction")
        raise exceptions.ReconstructionError
def share_and_recover(players, reconstruction_threshold, secret, end):
    '''
    Args:
        players, a list of unique player ids
        reconstruction_threshold, the threshold needed for secret reconstruction
        secret, the secret to be shared
        end, the number of shares to use in reconstruction
    Returns:
        the result of robust reconstruction
    '''
    max_secret_length = len(secret)
    shares_subset = get_shares_subset(players, reconstruction_threshold, secret, end)
    return rss.reconstruct_authenticated_secret(len(players), reconstruction_threshold, max_secret_length, shares_subset)
def corrupt_share_and_recover(num_players, reconstruction_threshold, max_secret_length, shares_subset, num_corrupt):
    '''
    Args:
        num_players, the number of players that were shared across
        reconstruction_threshold, the threshold for reconstruction
        max_secret_length, the maximum length of the secret that was shared
        shares_subset, a dictionary of a subset of players to json robust shares
        num_corrupt, the number of players that will corrupt their shares
    Returns:
        the result of robust reconstruction
    '''
    corrupters = {player: rss._deserialize_robust_share(share) for player, share in shares_subset.items()[:num_corrupt]}

    # corrupt share data
    for player, share_dict in corrupters.items():
        share_dict["share"] /= 4

    shares = combine_testing_dictionaries(shares_subset, jsonify_dict(corrupters))
    return rss.reconstruct_authenticated_secret(num_players, reconstruction_threshold, max_secret_length, shares)
def test_json_parse_make_key_dict_string():
    num_players = 8
    reconstruction_threshold = 4
    end = num_players
    num_broken = reconstruction_threshold - 1

    players = get_ids(num_players)
    shares_subset = get_shares_subset(players, reconstruction_threshold, secret, end)
    unjsonify_shares = {player: rss._deserialize_robust_share(share) for player, share in shares_subset.items()[:num_broken]}

    for player, share in unjsonify_shares.items():
        share["keys"] = str(share["keys"])

    shares = combine_testing_dictionaries(shares_subset, jsonify_dict(unjsonify_shares))

    recovered_secret, authorized_players, invalid_players = \
        rss.reconstruct_authenticated_secret(num_players, reconstruction_threshold, len(secret), shares)
    assert verify_results(recovered_secret, secret,
                          authorized_players, shares_subset.keys()[num_broken:],
                          invalid_players, shares_subset.keys()[:num_broken]) is True
def test_json_bracket_parse_error():
    num_players = 8
    reconstruction_threshold = 4
    end = num_players
    num_broken = reconstruction_threshold - 1

    players = get_ids(num_players)
    shares_subset = get_shares_subset(players, reconstruction_threshold, secret, end)

    broken_shares = {}
    for player, share in shares_subset.items()[:num_broken]:
        broken_shares[player] = share[1:]  # remove opening JSON bracket

    shares = combine_testing_dictionaries(shares_subset, broken_shares)

    recovered_secret, authorized_players, invalid_players = \
        rss.reconstruct_authenticated_secret(num_players, reconstruction_threshold, len(secret), shares)
    assert verify_results(recovered_secret, secret,
                          authorized_players, shares_subset.keys()[num_broken:],
                          invalid_players, shares_subset.keys()[:num_broken]) is True
def test_json_key_error():
    num_players = 8
    reconstruction_threshold = 4
    end = num_players
    num_broken = reconstruction_threshold - 1

    players = get_ids(num_players)
    shares_subset = get_shares_subset(players, reconstruction_threshold, secret, end)

    broken_shares = {}
    for player, share in shares_subset.items()[:num_broken]:
        keys_index = share.index("keys")
        share = share[:keys_index] + "pown" + share[keys_index + len("keys"):]
        broken_shares[player] = share

    shares = combine_testing_dictionaries(shares_subset, broken_shares)

    recovered_secret, authorized_players, invalid_players = \
        rss.reconstruct_authenticated_secret(num_players, reconstruction_threshold, len(secret), shares)
    assert verify_results(recovered_secret, secret,
                          authorized_players, shares_subset.keys()[num_broken:],
                          invalid_players, shares_subset.keys()[:num_broken]) is True
def corrupt_keys_and_recover(num_players, reconstruction_threshold, max_secret_length, shares_subset, num_corrupt, degree_of_corruption):
    '''
    Args:
        num_players, the number of players that were shared across
        reconstruction_threshold, the threshold for reconstruction
        max_secret_length, the maximum length of the secret that was shared
        shares_subset, a dictionary of a subset of players to json robust shares
        num_corrupt, the number of players that will corrupt auth keys
        degree_of_corruption, how many of the keys each corrupting player will corrupt
    Returns:
        the result of robust reconstruction
    '''
    corrupters = {player: rss._deserialize_robust_share(share) for player, share in shares_subset.items()[:num_corrupt]}
    verifiers = [player for player in shares_subset.keys()[:degree_of_corruption]]

    # corrupt key data
    for player, share_dict in corrupters.items():
        for verifier in verifiers:
            share_dict["keys"][verifier] /= 4

    shares = combine_testing_dictionaries(shares_subset, jsonify_dict(corrupters))
    return rss.reconstruct_authenticated_secret(num_players, reconstruction_threshold, max_secret_length, shares)
def test_various_parse_errors():
    reconstruction_threshold = 6
    num_broken = reconstruction_threshold - 1
    num_players = reconstruction_threshold + num_broken
    end = num_players

    players = get_ids(num_players)
    shares_subset = get_shares_subset(players, reconstruction_threshold, secret, end)

    unjsonify_shares = {player: rss._deserialize_robust_share(share) for player, share in shares_subset.items()}

    remove_vectors_player = players[0]
    remove_vectors_share = unjsonify_shares[remove_vectors_player]
    unjsonify_shares[remove_vectors_player]["vectors"] = {player: vector for player, vector in remove_vectors_share["vectors"].items()[:4]}

    remove_keys_player = players[1]
    remove_keys_share = unjsonify_shares[remove_keys_player]
    unjsonify_shares[remove_keys_player]["keys"] = {player: key for player, key in remove_keys_share["keys"].items()[:4]}

    make_share_string_player = players[2]
    unjsonify_shares[make_share_string_player]["share"] = str(unjsonify_shares[make_share_string_player]["share"])

    shares = jsonify_dict(unjsonify_shares)

    json_parse_player = players[3]
    shares[json_parse_player] = shares[json_parse_player][1:]  # remove starting bracket

    key_error_player = players[4]
    key_error_share = shares[key_error_player]
    keys_index = key_error_share.index("keys")
    shares[key_error_player] = key_error_share[:keys_index] + "pown" + key_error_share[keys_index + len("keys"):]

    recovered_secret, authorized_players, invalid_players = \
        rss.reconstruct_authenticated_secret(num_players, reconstruction_threshold, len(secret), shares)
    dishonest_players = [remove_vectors_player, remove_keys_player, make_share_string_player, json_parse_player, key_error_player]
    assert verify_results(recovered_secret, secret,
                          authorized_players, list(set(players) - set(dishonest_players)),
                          invalid_players, dishonest_players) is True