示例#1
0
def round0():
    start = time.time()
    #print(bcolors.BOLD + '\n--- Round 0 ---' + bcolors.ENDC)

    # Generate the 2 pair of Diffie-Hellman keys
    # "s" will be used to generate the seed for the shared mask, and "c" the shared encryption key
    my_ssk, my_spk = DHKE.generate_keys()
    my_csk, my_cpk = DHKE.generate_keys()

    # Store the previously generated keys
    CLIENT_VALUES['my_ssk'] = my_ssk; CLIENT_VALUES['my_spk'] = my_spk
    CLIENT_VALUES['my_csk'] = my_csk; CLIENT_VALUES['my_cpk'] = my_cpk

    #generate IBAS key for client step1

    
    Un = CLIENT_VALUES['my_sid']

    P_n0,P_n1,sP_n0,sP_n1 = ibas.PKG(Un)
    #print("IBASkey:",sP_n01,sP_n11)

    #store IBAS key
    CLIENT_VALUES['P_n0'] = P_n0
    CLIENT_VALUES['P_n1'] = P_n1
    CLIENT_VALUES['sP_n0'] = sP_n0
    CLIENT_VALUES['sP_n1'] = sP_n1

    #generate VEG key for client step1
    k_n, Kn = veg.generate_keys()

    #store veg key
    CLIENT_VALUES['k_n'] = k_n
    CLIENT_VALUES['Kn'] = Kn
    #print("VEGkey:",k_n,Kn) #right 10.12


    # Send the client's public key for "c" and "s" to the server
    #print_info('Sending pubkeys to server...', CLIENT_VALUES['my_sid'])

    #print("daxiao:",total_size({'cpk':my_cpk, 'spk':my_spk}))#10.16 daxiao

    end = time.time()
    timeofround0 = end - start
    
    CLIENT_VALUES['timeofround0'] = timeofround0
    clientround0totalsize = total_size({'cpk':my_cpk, 'spk':my_spk})
    print("timeofround0:",timeofround0,"clientround0totalsize:",clientround0totalsize)

    CLIENT_VALUES['clientround0totalsize'] = clientround0totalsize
    sio.emit('PUB_KEYS', {'cpk':my_cpk, 'spk':my_spk}, callback=server_ack)
示例#2
0
def server_side_private_set_union(communication, clients,
                                  union_security_para_dict, round_num,
                                  ps_computation_time_path):
    """
    Main function for parameter server to dominate private set union through perturbed Bloom filter and Secure Aggregation.
    """
    # This dictionary will contain the information that the server received from all clients.
    # It is keyed by client_index.
    UNION_SERVER_STORAGE = {}
    # This dictionary will mainly keep track of time, rounds, and set of (up-to-date) live clients
    UNION_ROUND_STORAGE = {}

    UNION_ROUND_STORAGE['communication_round_num'] = round_num
    UNION_ROUND_STORAGE['ps_computation_time_path'] = ps_computation_time_path

    # ID 14 - 2048-bit MODP group for Diffie-Hellman Key Exchange
    UNION_DHKE = DHKE(groupID=14)

    server_side_psu_round0(communication, clients, UNION_SERVER_STORAGE,
                           UNION_ROUND_STORAGE)
    server_side_psu_round1(communication, clients, UNION_SERVER_STORAGE,
                           UNION_ROUND_STORAGE)
    server_side_psu_round2(communication, clients, UNION_SERVER_STORAGE,
                           UNION_ROUND_STORAGE)
    bf_perturbed_sum = server_side_psu_round3(communication, clients, UNION_SERVER_STORAGE, UNION_ROUND_STORAGE, \
                                              union_security_para_dict, UNION_DHKE)
    real_itemIDs_union = (np.nonzero(bf_perturbed_sum)[0]).tolist()
    # send back union
    send_back_union_psu(communication, clients, real_itemIDs_union)
示例#3
0
def round0():

    #print(bcolors.BOLD + '\n--- Round 0 ---' + bcolors.ENDC)

    # Generate the 2 pair of Diffie-Hellman keys
    # "s" will be used to generate the seed for the shared mask, and "c" the shared encryption key
    my_ssk, my_spk = DHKE.generate_keys()
    my_csk, my_cpk = DHKE.generate_keys()

    # Store the previously generated keys
    CLIENT_VALUES['my_ssk'] = my_ssk
    CLIENT_VALUES['my_spk'] = my_spk
    CLIENT_VALUES['my_csk'] = my_csk
    CLIENT_VALUES['my_cpk'] = my_cpk

    # Send the client's public key for "c" and "s" to the server
    #print_info('Sending pubkeys to server...', CLIENT_VALUES['my_sid'])
    sio.emit('PUB_KEYS', {'cpk': my_cpk, 'spk': my_spk}, callback=server_ack)
示例#4
0
def client_side_secure_federated_submodel_averaging(communication, client_socket, client_index, fedsubavg_x_dict,\
          perturbed_itemIDs, perturbed_cateIDs, fedsubavg_security_para_dict, fedsubavg_u2_drop_flag, fedsubavg_u3_drop_flag,\
                                                    round_num, client_computation_time_path):
    """
    Main function for client to join secure federated submodel averaging through secure aggregation
    """
    # This dictionary will contain all the values generated by this client herself
    FEDSUBAVG_SELF_STORAGE = {}
    # This dictionary will contain all the values about the OTHER clients. It is keyed by client_index
    FEDSUBAVG_OTHERS_STORAGE = {}

    FEDSUBAVG_SELF_STORAGE['my_index'] = client_index
    FEDSUBAVG_SELF_STORAGE['communication_round_number'] = round_num
    FEDSUBAVG_SELF_STORAGE['client_computation_time_path'] = client_computation_time_path

    # ID 14 - 2048-bit MODP group for Diffie-Hellman Key Exchange
    FEDSUBAVG_DHKE = DHKE(groupID=14)
    client_side_sfsa_round0(communication, client_socket, FEDSUBAVG_SELF_STORAGE, FEDSUBAVG_OTHERS_STORAGE, FEDSUBAVG_DHKE)

    client_side_sfsa_round1(communication, client_socket, FEDSUBAVG_SELF_STORAGE, FEDSUBAVG_OTHERS_STORAGE, \
                           fedsubavg_security_para_dict, FEDSUBAVG_DHKE)

    if fedsubavg_u2_drop_flag:  # drop from round 2
        client_socket.close()
        print("Client %d drops out from Secure Federated Submodel Averaging U2 in this communication round \n" % client_index)
        print('-----------------------------------------------------------------')
        print('')
        print('')
        sys.stdout.flush()
        return

    # client's original inputs fedsubavg_x_dict: 'weighted_delta_submodel': uploaded_weighted_delta_submodel,
    #                         'perturbed_userID_count': uploaded_perturbed_userID_count,
    #                         'perturbed_itemIDs_count': uploaded_itemIDs_count,
    #                         'perturbed_cateIDs_count': uploaded_cateIDs_count,
    #                         'perturbed_other_count': uploaded_perturbed_other_count
    client_side_sfsa_round2(communication, client_socket, FEDSUBAVG_SELF_STORAGE, FEDSUBAVG_OTHERS_STORAGE, \
                            fedsubavg_x_dict, perturbed_itemIDs, perturbed_cateIDs, fedsubavg_security_para_dict, FEDSUBAVG_DHKE)

    if fedsubavg_u3_drop_flag:   # drop from round 3
        client_socket.close()
        print("Client %d drops out from Secure Federated Submodel Averaging U3 in this communication round \n" % client_index)
        print('-----------------------------------------------------------------')
        print('')
        print('')
        return

    client_side_sfsa_round3(communication, client_socket, FEDSUBAVG_SELF_STORAGE, FEDSUBAVG_OTHERS_STORAGE)

    del FEDSUBAVG_SELF_STORAGE
    del FEDSUBAVG_OTHERS_STORAGE
示例#5
0
def client_side_private_set_union(communication, client_socket, client_index,
                                  real_itemIDs, union_security_para_dict,
                                  union_u2_drop_flag, union_u3_drop_flag,
                                  round_num, client_computation_time_path):
    """
    Main function for client to join Private Set Union (PSU) through perturbed Bloom filter and Secure Aggregation
    """
    # This dictionary will contain all the values generated by this client herself
    UNION_SELF_STORAGE = {}
    # This dictionary will contain all the values about the OTHER clients. It is keyed by client_index
    UNION_OTHERS_STORAGE = {}
    UNION_SELF_STORAGE['my_index'] = client_index
    UNION_SELF_STORAGE['communication_round_number'] = round_num
    UNION_SELF_STORAGE[
        'client_computation_time_path'] = client_computation_time_path

    # ID 14 - 2048-bit MODP group for Diffie-Hellman Key Exchange
    UNION_DHKE = DHKE(groupID=14)
    client_side_psu_round0(communication, client_socket, UNION_SELF_STORAGE,
                           UNION_OTHERS_STORAGE, UNION_DHKE)
    client_side_psu_round1(communication, client_socket, UNION_SELF_STORAGE, UNION_OTHERS_STORAGE, \
                           union_security_para_dict, UNION_DHKE)

    if union_u2_drop_flag:  # drop from round 2
        client_socket.close()
        print(
            "Client %d drops out from Private Set Union U2 in this communication round \n"
            % client_index)
        print(
            '-----------------------------------------------------------------'
        )
        print('')
        print('')
        sys.stdout.flush()
        return []

    # Represent real_itemIDs as a perturbed Bloom filter
    start_time = time.time()
    real_itemIDs_pbf = represent_set_as_perturbed_bloom_filter(
        real_itemIDs, union_security_para_dict)

    write_csv(
        client_computation_time_path,
        [round_num, "psu_generated_perturbed_bf",
         time.time() - start_time])

    UNION_SELF_STORAGE['x'] = real_itemIDs_pbf
    client_side_psu_round2(communication, client_socket, UNION_SELF_STORAGE, UNION_OTHERS_STORAGE, \
                           union_security_para_dict, UNION_DHKE)

    if union_u3_drop_flag:  # drop from round 3
        client_socket.close()
        print(
            "Client %d drops out from Private Set Union U3 in this communication round \n"
            % client_index)
        print(
            '-----------------------------------------------------------------'
        )
        print('')
        print('')
        return []

    client_side_psu_round3(communication, client_socket, UNION_SELF_STORAGE,
                           UNION_OTHERS_STORAGE)

    # receive union
    real_itemIDs_union = communication.get_np_array(client_socket)
    print('Received union of real item ids (via Private Set Union).')
    sys.stdout.flush()

    del UNION_SELF_STORAGE
    del UNION_OTHERS_STORAGE

    return real_itemIDs_union
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from diffie_hellman import DHKE

from oblivious_transfer import OT_Sender, OT_Receiver

from AES_encryption import AESCipher

DHKE = DHKE(groupID=666)

# sk, pk = DHKE.generate_keys()
#
# print(sk)
# print('LENGTH:', len(str(sk)))
#
# print()
#
# shares = SecretSharer.split_secret(sk, 5, 6)
# # for s in shares:
# #     print('-', s)
# #     print('LENGTH:', len(str(s)))
# # print()
#
# secretTrue = SecretSharer.recover_secret(shares[0:5])
# print(secretTrue == sk)
#
# secretFalse = SecretSharer.recover_secret(shares[0:4]) # not enough
# print(secretFalse == sk)

sk1, pk1 = DHKE.generate_keys()
示例#7
0
def round3():

    U3 = SERVER_VALUES['U3']
    n3 = len(U3)
    print("|U3| the number of clients sending shared masks:", n3)
    if n3 < SERVER_VALUES['t']:
        print_failure(
            'Did not receive masks and shares from enough clients. Abort.',
            'Server')
        sio.emit(
            'abort', 'not enough clients'
        )  # Broadcast to everyone that the server aborts --> client should disconnect
        sio.sleep(1)
        os._exit(-1)  # sio.stop() # FIXME

    # The "dropped out clients" are all the clients sid that were present in the set U2 but not in U3
    dropped_out_clients = list(set(SERVER_VALUES['U2']) - set(U3))
    SERVER_VALUES['dropped_out_clients_round_3'] = dropped_out_clients

    Z = 0

    print("NB DROPPED OUT CLIENTS =",
          len(SERVER_VALUES['dropped_out_clients_round_2']))
    if SERVER_VALUES['dropped_out_clients_round_2'] != []:

        # Retrieve the shares of "ssk" of dropped out clients from all alive clients
        all_ssk_shares = []
        for client_sid in U3:
            all_ssk_shares.append(
                SERVER_STORAGE[client_sid]['ssk_shares_dropped'])

        ssk_shares_for_sid = {
            k: [d.get(k) for d in all_ssk_shares]
            for k in set().union(*all_ssk_shares)
        }

        # Reconstruct ssk from its shares
        ssk_for_sid = {}
        for client_sid in SERVER_VALUES['dropped_out_clients_round_2']:
            ssk = SecretSharer.recover_secret(ssk_shares_for_sid[client_sid])
            ssk_for_sid[client_sid] = ssk

        # Reconstruct all blinding values (s_masks) for all pairs of alive users with the dropped out users
        all_masks = np.zeros(NB_CLASSES)
        for dropped_client_sid in SERVER_VALUES['dropped_out_clients_round_2']:
            for alive_client_sid in U3:
                s_for_sid = DHKE.agree(ssk_for_sid[dropped_client_sid],
                                       SERVER_STORAGE[alive_client_sid]['spk'])
                np.random.seed(s_for_sid % 2**32)
                s_mask_for_sid = np.random.uniform(-UNIFORM_S_BOUNDS,
                                                   UNIFORM_S_BOUNDS,
                                                   NB_CLASSES)
                sgn = np.sign(
                    int(alive_client_sid, 16) - int(dropped_client_sid, 16))
                all_masks += sgn * s_mask_for_sid

        Z -= all_masks

    # Retrieve the shares of "b" from all alive clients
    all_b_shares = []
    for client_sid in U3:
        all_b_shares.append(SERVER_STORAGE[client_sid]['b_shares_alive'])

    b_shares_for_sid = {
        k: [d.get(k) for d in all_b_shares]
        for k in set().union(*all_b_shares)
    }

    # Reconstruct "b" from its shares
    b_for_sid = {}
    for client_sid in U3:
        b = SecretSharer.recover_secret(b_shares_for_sid[client_sid])
        b_for_sid[client_sid] = b

    # Remove b from the y that we received from clients, and aggregate the whole
    for client_sid in U3:
        b = b_for_sid[client_sid]
        np.random.seed(b)
        b_mask = np.random.uniform(-UNIFORM_B_BOUNDS, UNIFORM_B_BOUNDS,
                                   NB_CLASSES)
        Z += (SERVER_STORAGE[client_sid]['y'] - b_mask)

    print('Server succesfully aggregate the result and the lenth is ',
          len(list(Z)))

    # For Decentralized PATE, the label would be the argmax of this vote vector
    #print('LABEL:', np.argmax(Z))

    SERVER_VALUES['serverround3totalsize'] = total_size({
        "aggregation": list(Z),
        'U3': U3
    })

    sio.emit('ROUND_4', {"aggregation": list(Z), 'U3': U3})  #tianjia in 10.11

    # Go back to function call (ret) and exit in function timer_round3() above
    sio.start_background_task(timer_round_4)
示例#8
0
    UNIFORM_B_BOUNDS = 1e6  # Min and Max bounds for random b masking values
    UNIFORM_S_BOUNDS = 1e6  # Min and Max bounds for random s masking values

    # 2 sorts of measurements per round, COMMunication time, with the clients
    # and COMPutation time (only the server, processing the logic for this round)
    # Stored in SERVER_VALUES dict, as:
    # SERVER_VALUES['BENCHMARK_TIME_ROUND_i_COMP'] or SERVER_VALUES['BENCHMARK_TIME_ROUND_i_COMM']

    assert (len(sys.argv) == 3)
    INIT_NB_CLIENTS = int(sys.argv[1])
    BENCHMARK_FILENAME = sys.argv[2]

    # Initialization of the parameters (groupID 14) for the Diffie-Hellman
    # Key Exchange algorithm
    global DHKE
    DHKE = DHKE(groupID=14)

    # This dictionary will contain all the values used by the server
    # to keep track of time, rounds, and number of clients
    global SERVER_VALUES
    SERVER_VALUES = {}

    # This dictionary will contain the information that the server
    # received about all clients. It is keyed by client_sid.
    global SERVER_STORAGE
    SERVER_STORAGE = {}

    # Global variable "ROUND" tracking the Round Number --> Finite State Machine Logic of the server
    SERVER_VALUES['ROUND'] = 0

    app = Flask(__name__)
示例#9
0
def round2(enc_msgs):

    for client_sid, enc_msg in enc_msgs.items():

        # Decrypt the encrypted message and parse it
        enc_key_for_sid = CLIENT_STORAGE[client_sid]['enc_key']
        msg = AESCipher(str(enc_key_for_sid)).decrypt(enc_msg)

        msg_parts = msg.split(' || ')

        protocol_id = msg_parts[0]  # TODO: What's the use? #TODO: Timestamp?
        from_client_sid = msg_parts[1]
        my_sid = msg_parts[2]
        share_ssk_for_sid = msg_parts[3]
        share_a_for_sid = msg_parts[4]
        share_b_for_sid = msg_parts[5]

        # Store has been received for client_sid
        CLIENT_STORAGE[from_client_sid]['share_ssk'] = share_ssk_for_sid
        CLIENT_STORAGE[from_client_sid]['share_a'] = share_a_for_sid
        CLIENT_STORAGE[from_client_sid]['share_b'] = share_b_for_sid

        # Sanity check
        if client_sid != from_client_sid or my_sid != CLIENT_VALUES['my_sid']:
            print_failure('Received wrong message!', CLIENT_VALUES['my_sid'])
            sio.disconnect()

        # Derive secret shared mask seed s_for_sid (Diffie-Hellman Agreement)
        s_for_sid = DHKE.agree(CLIENT_VALUES['my_ssk'],
                               CLIENT_STORAGE[client_sid]
                               ['spk'])  #; print('s_for_sid =', s_for_sid)

        # Derive s_mask from above seed
        np.random.seed(
            s_for_sid %
            2**32)  # TODO: Higher entropy than 2**32??? (max value to .seed())
        s_mask_for_sid = np.random.uniform(
            -UNIFORM_S_BOUNDS, UNIFORM_S_BOUNDS, NB_CLASSES
        )  #; print('s_for_sid =', s_for_sid )# TODO: Which values??

        # Store also that
        CLIENT_STORAGE[client_sid]['s'] = s_for_sid
        CLIENT_STORAGE[client_sid]['s_mask'] = s_mask_for_sid

    # Construct masked input:
    # First the noisy input (the one that the server will aggregate)
    noisy_x = CLIENT_VALUES['x'] + CLIENT_VALUES['a_noise']

    # Then, add the individual mask
    yy = noisy_x + CLIENT_VALUES['b_mask']

    all_masks = np.zeros(NB_CLASSES)
    for client_sid in CLIENT_STORAGE.keys():
        if client_sid == CLIENT_VALUES['my_sid']:
            continue  # Skip my own SID
        if not 's_mask' in CLIENT_STORAGE[client_sid].keys():
            print_failure("No shared mask for client", client_sid)
            continue  # We do not have shared mask from this client SID
        sgn = np.sign(
            int(CLIENT_VALUES['my_sid'], 16) -
            int(client_sid, 16))  # Substract the masks of greater client SIDs,
        all_masks += sgn * CLIENT_STORAGE[client_sid][
            's_mask']  # or add those of smaller client SIDs

    # Here is the final output "y" to send to server
    y = yy + all_masks

    #print_info('Sending masked input "y" to server...', CLIENT_VALUES['my_sid'])
    sio.emit(
        'INPUT_Y', list(y), callback=server_ack
    )  # Send "y" as a python list because numpy arrays are not JSON-serializable
示例#10
0
def round1(pubkeys):

    # Store the keys received from the server, in the dictionary CLIENT_STORAGE, for each client_sid
    for client_sid, pubkeys_for_client_sid in pubkeys.items():
        if client_sid == CLIENT_VALUES['my_sid']:
            continue  # Does not need to store my own keys (already stored in CLIENT_VALUES)
        try:
            CLIENT_STORAGE.setdefault(
                client_sid, {})['cpk'] = pubkeys_for_client_sid['cpk']
            CLIENT_STORAGE.setdefault(
                client_sid, {})['spk'] = pubkeys_for_client_sid['spk']
        except KeyError:
            print_failure('Missing key cpk or spk in server'
                          's messsage.', request.sid)
            sio.disconnect()

    # Compute n, the number of active clients (me, included)
    n = len(CLIENT_STORAGE.keys()) + 1  #; print('n =', n)

    # Compute t, the minimum number of clients we need for the aggregation
    t = int(n / 2) + 1  #; print('t =', t)

    # Draw random seed a, and make a gaussian noise mask out of it
    a = secrets.randbits(32)  #; print('a =', a) # TODO: Chose higher entropy
    np.random.seed(a)
    a_noise_vector = np.random.normal(
        0,
        float(SIGMA) / np.sqrt(t),
        NB_CLASSES)  #; print('a_noise_vector =', a_noise_vector)

    # Draw random seed b, and make a mask out of it
    b = secrets.randbits(32)  #; print('b =', b)
    np.random.seed(b)
    b_mask = np.random.uniform(
        -UNIFORM_B_BOUNDS, UNIFORM_B_BOUNDS, NB_CLASSES
    )  #; print('b_mask =', b_mask) # TODO: HOW TO CHOOSE THOSE VALUES???

    # Create t-out-of-n shares for seed a
    shares_a = SecretSharer.split_secret(a, t,
                                         n)  #; print('shares_a =', shares_a)

    # Create t-out-of-n shares for seed b
    shares_b = SecretSharer.split_secret(b, t,
                                         n)  #; print('shares_b =', shares_b)

    # Create t-out-of-n shares for my private key my_ssk (as an hex_string)
    shares_my_ssk = SecretSharer.split_secret(
        CLIENT_VALUES['my_ssk'], t,
        n)  #; print('shares_my_ssk =', shares_my_ssk)

    # Store all the previously generated values, in client's dictionary
    CLIENT_VALUES['n'] = n
    CLIENT_VALUES['t'] = t

    CLIENT_VALUES['a'] = a
    CLIENT_VALUES['a_noise'] = a_noise_vector
    CLIENT_VALUES['b'] = b
    CLIENT_VALUES['b_mask'] = b_mask

    CLIENT_VALUES['shares_a'] = shares_a
    CLIENT_VALUES['shares_b'] = shares_b
    CLIENT_VALUES['shares_my_ssk'] = shares_my_ssk

    # Store my share of b in isolation:
    my_share_b = shares_b[0]
    shares_b = list(set(shares_b) - set([my_share_b]))
    CLIENT_VALUES['my_share_b'] = my_share_b

    list_encrypted_messages = {}
    for ID, client_sid in enumerate(CLIENT_STORAGE.keys()):

        if client_sid == CLIENT_VALUES['my_sid']:
            continue  # Skip my own sid # FIXME: Actually, I am NOT part of CLIENT_STORAGE.keys()

        # Derive encryption key enc_key_for_sid (via Diffie-Hellman Agreement)
        enc_key_for_sid = DHKE.agree(
            CLIENT_VALUES['my_csk'], CLIENT_STORAGE[client_sid]
            ['cpk'])  #; print('enc_key_for_sid =', enc_key_for_sid)

        # Client "client_sid" will be sent this message:
        msg = 'ProtoV1.0' + ' || ' + str(
            CLIENT_VALUES['my_sid']) + ' || ' + str(client_sid) + ' || ' + str(
                shares_my_ssk[ID]) + ' || ' + str(shares_a[ID]) + ' || ' + str(
                    shares_b[ID])

        # Encrypt the message with the pre-derived shared encryption key
        enc_msg = AESCipher(str(enc_key_for_sid)).encrypt(msg)

        # Store the encrypted messages in a dictionary (keyed by client_sid) that will be sent to the server
        list_encrypted_messages[client_sid] = enc_msg

        CLIENT_STORAGE[client_sid]['enc_key'] = enc_key_for_sid
        CLIENT_STORAGE[client_sid]['msg'] = msg
        CLIENT_STORAGE[client_sid]['enc_msg'] = enc_msg

    #print_info('Sending list of encrypted messages to server...', CLIENT_VALUES['my_sid'])
    sio.emit('ENC_MSGS', list_encrypted_messages, callback=server_ack)

    if WILL_CRASH:
        sio.sleep(1)
        os._exit(0)
示例#11
0
    NB_CLASSES = 10
    SIGMA = 0.005

    # This dictionary will contain all the values generated by this client
    # and used in the aggregation
    global CLIENT_VALUES
    CLIENT_VALUES = {}

    # This dictionary will contain all the values about the OTHER clients
    # part of the aggregation. It is keyed by client_sid.
    global CLIENT_STORAGE
    CLIENT_STORAGE = {}

    # The params of the group
    global DHKE
    DHKE = DHKE(groupID=14)  # TODO: Use 2048-bit group (id=14) or above

    # The socketIO object representing our client's socket.
    # We can register listeners ('handlers') of events with the function sio.on(<event name>, <handler function>)
    sio = socketio.Client()

    # Connect this client to the server. Upon connection, this client receives a unique socket id "my_sid"
    # that we store in the CLIENT_VALUES
    sio.connect('http://127.0.0.1:9876'
                )  # TODO: Put address and port in a server.ini config file
    CLIENT_VALUES['my_sid'] = sio.eio.sid

    #print('My sid =', CLIENT_VALUES['my_sid'])

    # "connect" and "disconnect" are 2 special events generated by socketIO upon socket creation
    # and destruction. "abort" is a custom event that we created upon server stopping.
示例#12
0
def round2(round1servertoclientmessages):
    #print("round1servertoclientmessages:",round1servertoclientmessages) success 10.10
    
    for client_sid, enc_msg in round1servertoclientmessages["enc_msgs"].items():

        # Decrypt the encrypted message and parse it
        enc_key_for_sid = CLIENT_STORAGE[client_sid]['enc_key']
        msg = PrpCrypt(str(enc_key_for_sid)).decrypt(enc_msg)

        msg_parts = msg.split(' || ')

        protocol_id = msg_parts[0] # TODO: What's the use? #TODO: Timestamp?
        from_client_sid = msg_parts[1]
        my_sid = msg_parts[2]
        share_ssk_for_sid = msg_parts[3]
        share_b_for_sid = msg_parts[4]

        # Store has been received for client_sid
        CLIENT_STORAGE[from_client_sid]['share_ssk'] = share_ssk_for_sid
        #CLIENT_STORAGE[from_client_sid]['share_a'] = share_a_for_sid
        CLIENT_STORAGE[from_client_sid]['share_b'] = share_b_for_sid

        # Sanity check
        if client_sid != from_client_sid or my_sid != CLIENT_VALUES['my_sid']:
            print_failure('Received wrong message!', CLIENT_VALUES['my_sid'])
            sio.disconnect()

        # Derive secret shared mask seed s_for_sid (Diffie-Hellman Agreement)
        s_for_sid = DHKE.agree(CLIENT_VALUES['my_ssk'], CLIENT_STORAGE[client_sid]['spk'])         #; print('s_for_sid =', s_for_sid)

        # Derive s_mask from above seed
        np.random.seed(s_for_sid % 2**32) # TODO: Higher entropy than 2**32??? (max value to .seed())
        s_mask_for_sid = np.random.uniform(-UNIFORM_S_BOUNDS, UNIFORM_S_BOUNDS, NB_CLASSES)                                  #; print('s_for_sid =', s_for_sid )# TODO: Which values??

        # Store also that
        CLIENT_STORAGE[client_sid]['s'] = s_for_sid
        CLIENT_STORAGE[client_sid]['s_mask'] = s_mask_for_sid


    # Construct masked input:
    yy = CLIENT_VALUES['x'] + CLIENT_VALUES['b_mask']

    #the second masked in our paper
    all_masks = np.zeros(NB_CLASSES)
    for client_sid in CLIENT_STORAGE.keys():
        if client_sid == CLIENT_VALUES['my_sid']:
            continue # Skip my own SID
        if not 's_mask' in CLIENT_STORAGE[client_sid].keys():
            print_failure("No shared mask for client", client_sid)
            continue # We do not have shared mask from this client SID
        sgn = np.sign(int(CLIENT_VALUES['my_sid'], 16) - int(client_sid, 16))  # Substract the masks of greater client SIDs,
        all_masks += sgn * CLIENT_STORAGE[client_sid]['s_mask']                # or add those of smaller client SIDs

    # Here is the final output "y" to send to server
    y = yy + all_masks

    '''
    Identity-Based Aggregate Signatures
    ->round0 & round 2 
    data:10.10
    '''
    '''individual signing step 2'''
    start = time.time()
    #extract sessionID from the message received from the server
    sessionID = round1servertoclientmessages['SID']
    #print("client receive SID",sessionID)
    
    #store the sessionID

    CLIENT_VALUES["sessionID"] = sessionID

    #calculate w by sessionID
    sha1 = hashlib.sha1()
    sha1.update(str(sessionID).encode("utf-8"))#str(sessionID) list ->string
    w = str(sha1.hexdigest())
    #w = "w" test first  
    #print("w->",w)

    P_n0 = CLIENT_VALUES['P_n0']
    P_n1 = CLIENT_VALUES['P_n1']
    sP_n0 = CLIENT_VALUES['sP_n0']
    sP_n1 = CLIENT_VALUES['sP_n1']

    Un = CLIENT_VALUES['my_sid']
    k_n = CLIENT_VALUES['k_n']
    Kn = CLIENT_VALUES['Kn']

    #VElGamal encryption
    x_n = []
    for i in range(NB_CLASSES):
        x_n.append(int(CLIENT_VALUES['x'][i]*1e6))

    #print("x_n",x_n)

    Cn = veg.enc(x_n,k_n)

    #construct Mn
    Mn= str(Kn)+str(Cn)+str(sessionID)
    sigma_n = ibas.InSign(w,Mn,Un,sP_n0,sP_n1)
    #print("Individual signature:", sigma_n)
    c_n = Element.from_hash(pairing, Zr, Un + Mn + w)

    #print("c_n",c_n,type(c_n))
    #print("P_n0",P_n0,type(P_n0))
    #print("P_n1",P_n1,type(P_n1))

    strsigma_n = [sigma_n[0],str(sigma_n[1]),str(sigma_n[2])] #shoud be convert to pypbc.Element.G2
    strc_n = str(c_n)#in fact it should by reconstruct though little computation cost
    strP_n0 = str(P_n0)
    strP_n1 = str(P_n1)

    round2clienttoservermessages = {"mask_x":list(y),"sigma_n":strsigma_n,"Cn":Cn,"Kn":Kn,"c_n":strc_n,"P_n0":strP_n0,"P_n1":strP_n1,'w':w}

    #print_info('Sending masked input "y" to server...', CLIENT_VALUES['my_sid'])
    end = time.time()
    timeofround2 = end - start
    CLIENT_VALUES['timeofround2'] = timeofround2
    clientround2totalsize = total_size(round2clienttoservermessages)
    CLIENT_VALUES['clientround2totalsize'] = clientround2totalsize

    print("timeofround2:",timeofround2,"clientround2totalsize:",clientround2totalsize)
    sio.emit('INPUT_Y', round2clienttoservermessages, callback=server_ack) # Send "y" as a python list because numpy arrays are not JSON-serializable
示例#13
0
def round1(pubkeys):
    start = time.time()
    # Store the keys received from the server, in the dictionary CLIENT_STORAGE, for each client_sid
    for client_sid, pubkeys_for_client_sid in pubkeys.items():
        if client_sid == CLIENT_VALUES['my_sid']:
            continue # Does not need to store my own keys (already stored in CLIENT_VALUES)
        try:
            CLIENT_STORAGE.setdefault(client_sid, {})['cpk'] = pubkeys_for_client_sid['cpk']#当查找的键值 key 不存在的时候,setdefault()函数会返回默认值并更新字典,添加键值
            CLIENT_STORAGE.setdefault(client_sid, {})['spk'] = pubkeys_for_client_sid['spk']
        except KeyError:
            print_failure('Missing key cpk or spk in server''s messsage.', client_sid)
            sio.disconnect()

    # Compute n, the number of active clients (me, included)
    n = len(CLIENT_STORAGE.keys()) + 1                                                           #; print('n =', n)

    # Compute t, the minimum number of clients we need for the aggregation
    t = int(n/2) + 1                                                                             #; print('t =', t)

    

    # Draw random seed b, and make a mask out of it
    b = secrets.randbits(32)                                                                    #; print('b =', b)
    np.random.seed(b)
    b_mask = np.random.uniform(-UNIFORM_B_BOUNDS, UNIFORM_B_BOUNDS, NB_CLASSES)                 #; print('b_mask =', b_mask) # TODO: HOW TO CHOOSE THOSE VALUES???

    # Create t-out-of-n shares for seed b
    shares_b = SecretSharer.split_secret(b, t, n)                                               #; print('shares_b =', shares_b)

    # Create t-out-of-n shares for my private key my_ssk (as an hex_string)
    shares_my_ssk = SecretSharer.split_secret(CLIENT_VALUES['my_ssk'], t, n)                    #; print('shares_my_ssk =', shares_my_ssk)


    # Store all the previously generated values, in client's dictionary
    CLIENT_VALUES['n'] = n; CLIENT_VALUES['t'] = t

    
    CLIENT_VALUES['b'] = b; CLIENT_VALUES['b_mask'] = b_mask

    #CLIENT_VALUES['shares_a'] = shares_a
    CLIENT_VALUES['shares_b'] = shares_b
    CLIENT_VALUES['shares_my_ssk'] = shares_my_ssk

    # Store my share of b in isolation:
    my_share_b = shares_b[0]
    shares_b = list( set(shares_b) - set([my_share_b]) )
    CLIENT_VALUES['my_share_b'] = my_share_b

    list_encrypted_messages = {}
    for ID, client_sid in enumerate(CLIENT_STORAGE.keys()):

        if client_sid == CLIENT_VALUES['my_sid']:
            continue # Skip my own sid # FIXME: Actually, I am NOT part of CLIENT_STORAGE.keys()

        # Derive encryption key enc_key_for_sid (via Diffie-Hellman Agreement)
        enc_key_for_sid = DHKE.agree(CLIENT_VALUES['my_csk'], CLIENT_STORAGE[client_sid]['cpk'])             #; print('enc_key_for_sid =', enc_key_for_sid)

        # Client "client_sid" will be sent this message:
        msg = 'ProtoV1.0' + ' || ' + str(CLIENT_VALUES['my_sid']) + ' || ' + str(client_sid) + ' || ' + str(shares_my_ssk[ID]) + ' || ' + str(shares_b[ID])

        # Encrypt the message with the pre-derived shared encryption key
        enc_msg = PrpCrypt(str(enc_key_for_sid)).encrypt(msg)

        # Store the encrypted messages in a dictionary (keyed by client_sid) that will be sent to the server
        list_encrypted_messages[client_sid] = enc_msg


        CLIENT_STORAGE[client_sid]['enc_key'] = enc_key_for_sid
        CLIENT_STORAGE[client_sid]['msg'] = msg
        CLIENT_STORAGE[client_sid]['enc_msg'] = enc_msg

       

     #Generate Rn*************************************
    Rn = random.randint(1,1000)
    CLIENT_VALUES["Rn"] = Rn

    round1clienttoservermessages = {"Rn":Rn, "enc_msg":list_encrypted_messages}
    
    end = time.time()
    timeofround1 = end - start
    
    CLIENT_VALUES['timeofround1'] = timeofround1

    clientround1totalsize = total_size(round1clienttoservermessages)
    CLIENT_VALUES['clientround1totalsize'] = clientround1totalsize

    print("timeofround1:",timeofround1,"clientround1totalsize:",clientround1totalsize)

    sio.emit('ENC_MSGS', round1clienttoservermessages, callback=server_ack)
    # drop out in round 1 set(U1) - set(U0)

    if WILL_CRASH:
        sio.sleep(1)
        os._exit(0)
示例#14
0
def round3():

    U3 = SERVER_VALUES['U3']
    n3 = len(U3)
    if n3 < SERVER_VALUES['t']:
        print_failure(
            'Did not receive masks and shares from enough clients. Abort.',
            'Server')
        sio.emit(
            'abort', 'not enough clients'
        )  # Broadcast to everyone that the server aborts --> client should disconnect
        sio.sleep(1)
        os._exit(-1)  # sio.stop() # FIXME

    # The "dropped out clients" are all the clients sid that were present in the set U2 but not in U3
    dropped_out_clients = list(set(SERVER_VALUES['U2']) - set(U3))
    SERVER_VALUES['dropped_out_clients_round_3'] = dropped_out_clients

    Z = 0

    print("NB DROPPED OUT CLIENTS =",
          len(SERVER_VALUES['dropped_out_clients_round_2']))

    if SERVER_VALUES['dropped_out_clients_round_2'] != []:

        # Retrieve the shares of "ssk" of dropped out clients from all alive clients
        all_ssk_shares = []
        for client_sid in U3:
            all_ssk_shares.append(
                SERVER_STORAGE[client_sid]['ssk_shares_dropped'])

        ssk_shares_for_sid = {
            k: [d.get(k) for d in all_ssk_shares]
            for k in set().union(*all_ssk_shares)
        }

        # Reconstruct ssk from its shares
        ssk_for_sid = {}
        for client_sid in SERVER_VALUES['dropped_out_clients_round_2']:
            ssk = SecretSharer.recover_secret(ssk_shares_for_sid[client_sid])
            ssk_for_sid[client_sid] = ssk

        # Reconstruct all blinding values (s_masks) for all pairs of alive users with the dropped out users
        all_masks = np.zeros(NB_CLASSES)
        for dropped_client_sid in SERVER_VALUES['dropped_out_clients_round_2']:
            for alive_client_sid in U3:
                s_for_sid = DHKE.agree(ssk_for_sid[dropped_client_sid],
                                       SERVER_STORAGE[alive_client_sid]['spk'])
                np.random.seed(s_for_sid % 2**32)
                s_mask_for_sid = np.random.uniform(-UNIFORM_S_BOUNDS,
                                                   UNIFORM_S_BOUNDS,
                                                   NB_CLASSES)
                sgn = np.sign(
                    int(alive_client_sid, 16) - int(dropped_client_sid, 16))
                all_masks += sgn * s_mask_for_sid

        Z -= all_masks

    # Retrieve the shares of "b" from all alive clients
    all_b_shares = []
    for client_sid in U3:
        all_b_shares.append(SERVER_STORAGE[client_sid]['b_shares_alive'])

    b_shares_for_sid = {
        k: [d.get(k) for d in all_b_shares]
        for k in set().union(*all_b_shares)
    }

    # Reconstruct "b" from its shares
    b_for_sid = {}
    for client_sid in U3:
        b = SecretSharer.recover_secret(b_shares_for_sid[client_sid])
        b_for_sid[client_sid] = b

    # Remove b from the y that we received from clients, and aggregate the whole
    for client_sid in U3:
        b = b_for_sid[client_sid]
        np.random.seed(b)
        b_mask = np.random.uniform(-UNIFORM_B_BOUNDS, UNIFORM_B_BOUNDS,
                                   NB_CLASSES)
        Z += (SERVER_STORAGE[client_sid]['y'] - b_mask)

    # More noise that neccesary (t), remove that extra noise
    if 'extra_noises' in SERVER_VALUES:
        extra_noises = np.array(SERVER_VALUES['extra_noises'])
        extra_noises_sum = np.sum(extra_noises, axis=0)

        Z -= extra_noises_sum

    # Z is now the approriately noised array, containing the aggregation of private
    # vectors of the still alive clients
    # print('Z = ', Z)
    print('[*]', time.time(), 'Done')

    # For Decentralized PATE, the label would be the argmax of this vote vector
    #print('LABEL:', np.argmax(Z))

    sio.emit('complete', 'Reconstructed output z!')