示例#1
0
def psu_reconstruct_single_mutual_mask(client_index_drop, client_index_live, union_s_shares_drop, union_live_spk, \
                                       UNION_DHKE, union_security_para_dict):
    """
    Assistant function for reconstructing mutual masks in parallel. (Single process)
    """
    # Load parameters for PRNG
    seed_len = union_security_para_dict['seed_len']
    security_strength = union_security_para_dict['security_strength']
    modulo_r_len = union_security_para_dict['modulo_r_len']
    item_count = union_security_para_dict[
        'item_count']  # length of perturbed Bloom filter (x)

    union_drop_ssk = SecretSharer.recover_secret(union_s_shares_drop)

    # Derive seed for mutual mask, i.e., agreed key, (u, v via Diffie-Hellman Agreement)
    s_uv = UNION_DHKE.agree(union_drop_ssk, union_live_spk)
    s_uv_modulo = s_uv % (2**seed_len)
    s_uv_entropy = int2bytes(s_uv_modulo, seed_len / 8)
    union_DRGB_s = HMAC_DRBG(s_uv_entropy, security_strength)
    union_s_mask = prng(union_DRGB_s, modulo_r_len, security_strength,
                        item_count)
    sgn = np.sign(client_index_live - client_index_drop)
    union_sgn_s_mask = sgn * union_s_mask
    union_sgn_s_mask = union_sgn_s_mask.astype('int64')
    return union_sgn_s_mask
示例#2
0
def server_side_psu_reconstruct_self_mask(UNION_SERVER_STORAGE,
                                          UNION_ROUND_STORAGE,
                                          union_security_para_dict):
    """
    Reconstruct the random seed b and thus self mask for each live client in U2 using the shares from U3.
    """
    union_all_b_shares = []
    for client_index in UNION_ROUND_STORAGE['U3']:
        union_all_b_shares.append(
            UNION_SERVER_STORAGE[client_index]['live_b_shares'])
    union_b_shares_dict = {
        k: [d.get(k) for d in union_all_b_shares]
        for k in set().union(*union_all_b_shares)  # U2
    }
    # Reconstruct and add up each self mask by PRNG expanding using the seed b
    # Load parameters for PRNG
    seed_len = union_security_para_dict['seed_len']
    security_strength = union_security_para_dict['security_strength']
    modulo_r_len = union_security_para_dict['modulo_r_len']
    item_count = union_security_para_dict[
        'item_count']  # length of perturbed Bloom filter (x)
    # Store sum result
    union_b_mask_sum = np.zeros(item_count, dtype='int64')

    # NOT U3!!!!!!! SHOULD BE U2, those clients who send masked input y
    for client_index in UNION_ROUND_STORAGE['U2']:
        union_b = SecretSharer.recover_secret(
            union_b_shares_dict[client_index])
        union_b_entropy = int2bytes(union_b, seed_len / 8)
        union_DRBG_b = HMAC_DRBG(union_b_entropy, security_strength)
        union_b_mask = prng(union_DRBG_b, modulo_r_len, security_strength,
                            item_count)
        union_b_mask_sum += union_b_mask
    return union_b_mask_sum
def psu_reconstruct_single_self_mask(union_b_shares, union_security_para_dict):
    """
    Assistant function for reconstructing self masks in parallel. (Single process)
    """
    # Load parameters for PRNG
    seed_len = union_security_para_dict['seed_len']
    security_strength = union_security_para_dict['security_strength']
    modulo_r_len = union_security_para_dict['modulo_r_len']
    item_count = union_security_para_dict['item_count']  # length of perturbed Bloom filter (x)

    union_b = SecretSharer.recover_secret(union_b_shares)
    union_b_entropy = int2bytes(union_b, seed_len / 8)
    union_DRBG_b = HMAC_DRBG(union_b_entropy, security_strength)
    union_b_mask = prng(union_DRBG_b, modulo_r_len, security_strength, item_count)
    union_b_mask = union_b_mask.astype('int64')
    return union_b_mask
示例#4
0
def server_side_psu_reconstruct_mutual_mask(UNION_SERVER_STORAGE,
                                            UNION_ROUND_STORAGE,
                                            union_security_para_dict,
                                            UNION_DHKE):
    """
    Reconstruct the secret key ssk and thus mutual mask for each dropped client in U1\U2 using the shares from U3.
    """
    item_count = union_security_para_dict[
        'item_count']  # length of perturbed Bloom filter (x)
    # Store sum result
    union_s_mask_sum = np.zeros(item_count, dtype='int64')
    if len(UNION_ROUND_STORAGE['U1\U2']
           ) == 0:  # Deal with special case no client drops in U2
        return union_s_mask_sum

    union_all_s_shares = []
    for client_index in UNION_ROUND_STORAGE['U3']:
        union_all_s_shares.append(
            UNION_SERVER_STORAGE[client_index]['drop_s_shares'])
    union_s_shares_dict = {
        k: [d.get(k) for d in union_all_s_shares]
        for k in set().union(*union_all_s_shares)  # U1\U2
    }
    # Reconstruct and add up each mutual mask (pair of each dropped client in U1/U2 with each live client in U2)
    # by PRNG expanding using the secret key ssk
    # Load parameters for PRNG
    seed_len = union_security_para_dict['seed_len']
    security_strength = union_security_para_dict['security_strength']
    modulo_r_len = union_security_para_dict['modulo_r_len']

    for client_index_drop in UNION_ROUND_STORAGE['U1\U2']:
        union_drop_ssk = SecretSharer.recover_secret(
            union_s_shares_dict[client_index_drop])
        # NOT U3!!!!!!! SHOULD BE U2, those clients who send masked input y.
        for client_index_live in UNION_ROUND_STORAGE['U2']:
            union_live_spk = UNION_SERVER_STORAGE[client_index_live]['spk']
            # Derive seed for mutual mask, i.e., agreed key, (u, v via Diffie-Hellman Agreement)
            s_uv = UNION_DHKE.agree(union_drop_ssk, union_live_spk)
            s_uv_modulo = s_uv % (2**seed_len)
            s_uv_entropy = int2bytes(s_uv_modulo, seed_len / 8)
            union_DRGB_s = HMAC_DRBG(s_uv_entropy, security_strength)
            union_s_mask = prng(union_DRGB_s, modulo_r_len, security_strength,
                                item_count)
            sgn = np.sign(client_index_live - client_index_drop)
            union_s_mask_sum += sgn * union_s_mask
    return union_s_mask_sum
示例#5
0
def client_side_psu_round1(communication, client_socket, UNION_SELF_STORAGE, UNION_OTHERS_STORAGE, \
                           union_security_para_dict, UNION_DHKE):
    """
    Generate and send encrypted secret shares for PRNG seed and ssk
    """
    start_time_1 = time.time()
    # Generate seed for PRNG
    seed_len = union_security_para_dict['seed_len']
    union_b_entropy = os.urandom(seed_len / 8)  #bytes
    union_b = bytes2int(union_b_entropy)

    t = UNION_SELF_STORAGE['t']
    n = UNION_SELF_STORAGE['n']
    # Generate t-out-of-n shares for PRNG's seed b
    union_shares_b = SecretSharer.split_secret(union_b, t, n)
    # Generate t-out-of-n shares for client's ssk
    union_shares_my_ssk = SecretSharer.split_secret(
        UNION_SELF_STORAGE['my_ssk'], t, n)

    # Store random seed, and secret shares into self dictionary
    UNION_SELF_STORAGE['b_entropy'] = union_b_entropy
    '''
    UNION_SELF_STORAGE['b'] = union_b
    UNION_SELF_STORAGE['shares_b'] = union_shares_b
    UNION_SELF_STORAGE['shares_my_ssk'] = union_shares_my_ssk
    '''

    # Store my share of b in isolation
    # No need to store my share of my ssk, since I am alive to myself!
    union_my_share_b = union_shares_b[0]
    union_shares_b = list(set(union_shares_b) - set([union_my_share_b]))
    UNION_SELF_STORAGE['my_share_b'] = union_my_share_b

    union_ss_ciphers_dict = {}
    for idx, client_index in enumerate(UNION_OTHERS_STORAGE.keys()):
        # Derive symmetric encryption key "agreed" with other client (with client_index) (via Diffie-Hellman Agreement)
        sym_enc_key = UNION_DHKE.agree(
            UNION_SELF_STORAGE['my_csk'],
            UNION_OTHERS_STORAGE[client_index]['cpk'])
        # Send ciphertext to other client (with client_index), where PS works as a mediation
        msg = str(UNION_SELF_STORAGE['my_index']) + ' || ' + str(client_index) + ' || ' + str(union_shares_b[idx]) \
              + ' || ' + str(union_shares_my_ssk[idx])
        # Encrypt with AES_CBC
        enc_msg = AESCipher(str(sym_enc_key)).encrypt(msg)
        union_ss_ciphers_dict[client_index] = enc_msg

        UNION_OTHERS_STORAGE[client_index]['sym_enc_key'] = sym_enc_key
        '''
        UNION_OTHERS_STORAGE[client_index]['msg'] = msg
        UNION_OTHERS_STORAGE[client_index]['enc_msg'] = enc_msg
        '''
    end_time_1 = time.time()

    # send encrypted shares to the server
    union_ss_ciphers_send_message = {
        'client_ID': UNION_SELF_STORAGE['my_index'],
        'ss_ciphers': union_ss_ciphers_dict
    }
    communication.send_np_array(union_ss_ciphers_send_message, client_socket)
    print(
        'Client %d sent encrypted secret shares to server in private set union'
        % UNION_SELF_STORAGE['my_index'])
    sys.stdout.flush()

    # receive other clients' encrypted shares to me from the server
    ss_ciphers_dict_received = communication.get_np_array(client_socket)
    print("Received other clients' encrypted secret shares from server.")
    sys.stdout.flush()

    start_time_2 = time.time()

    for client_index, enc_msg in ss_ciphers_dict_received.items():
        # Decrypt the encrypted message and parse it
        sym_enc_key = UNION_OTHERS_STORAGE[client_index]['sym_enc_key']
        msg = AESCipher(str(sym_enc_key)).decrypt(enc_msg)
        msg_parts = msg.split(' || ')
        # Sanity check
        from_client_index = int(msg_parts[0])
        my_index = int(msg_parts[1])
        assert from_client_index == client_index and my_index == UNION_SELF_STORAGE[
            'my_index']
        # Store secret shares of other clients
        UNION_OTHERS_STORAGE[client_index]['share_b'] = msg_parts[2]
        UNION_OTHERS_STORAGE[client_index]['share_ssk'] = msg_parts[3]
    # clients in U1 (except myself) for mutual masks
    UNION_SELF_STORAGE[
        'mutual_mask_client_indices'] = ss_ciphers_dict_received.keys()

    end_time_2 = time.time()
    write_csv(UNION_SELF_STORAGE['client_computation_time_path'], [UNION_SELF_STORAGE['communication_round_number'], \
                                        "psu_U1", end_time_1 - start_time_1 + end_time_2 - start_time_2])
示例#6
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)
示例#7
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)
def client_side_sfsa_round1(communication, client_socket, FEDSUBAVG_SELF_STORAGE, FEDSUBAVG_OTHERS_STORAGE, \
                           fedsubavg_security_para_dict, FEDSUBAVG_DHKE):
    """
    Generate and send encrypted secret shares for PRNG seed and ssk.
    This can be merged with that in private set union, but for clarity, we still do not do so.
    Different from private set union here is that, the client also receives the indices of other clients for
    mutual mask. Specifically, we need to handle mutual masks for the embedding layers of item ids and cate ids
    in a ``submodel" way.
    """
    start_time_1 = time.time()
    # Generate seed for PRNG
    seed_len = fedsubavg_security_para_dict['seed_len']
    fedsubavg_b_entropy = os.urandom(seed_len / 8)  #bytes
    fedsubavg_b = bytes2int(fedsubavg_b_entropy)

    t = FEDSUBAVG_SELF_STORAGE['t']
    n = FEDSUBAVG_SELF_STORAGE['n']
    # Generate t-out-of-n shares for PRNG's seed b
    fedsubavg_shares_b = SecretSharer.split_secret(fedsubavg_b, t, n)
    # Generate t-out-of-n shares for client's ssk
    fedsubavg_shares_my_ssk = SecretSharer.split_secret(
        FEDSUBAVG_SELF_STORAGE['my_ssk'], t, n)

    # Store random seed, and secret shares into self dictionary
    FEDSUBAVG_SELF_STORAGE['b_entropy'] = fedsubavg_b_entropy
    '''
    FEDSUBAVG_SELF_STORAGE['b'] = fedsubavg_b
    FEDSUBAVG_SELF_STORAGE['shares_b'] = fedsubavg_shares_b
    FEDSUBAVG_SELF_STORAGE['shares_my_ssk'] = fedsubavg_shares_my_ssk
    '''

    # Store my share of b in isolation
    # No need to store my share of my ssk, since I am alive to myself!
    fedsubavg_my_share_b = fedsubavg_shares_b[0]
    fedsubavg_shares_b = list(
        set(fedsubavg_shares_b) - set([fedsubavg_my_share_b]))
    FEDSUBAVG_SELF_STORAGE['my_share_b'] = fedsubavg_my_share_b

    fedsubavg_ss_ciphers_dict = {}
    for idx, client_index in enumerate(
            FEDSUBAVG_OTHERS_STORAGE.keys()):  # Already except myself
        # Derive symmetric encryption key "agreed" with other client (with client_index) (via Diffie-Hellman Agreement)
        sym_enc_key = FEDSUBAVG_DHKE.agree(
            FEDSUBAVG_SELF_STORAGE['my_csk'],
            FEDSUBAVG_OTHERS_STORAGE[client_index]['cpk'])
        # Send ciphertext to other client (with client_index), where PS works as a mediation
        msg = str(FEDSUBAVG_SELF_STORAGE['my_index']) + ' || ' + str(client_index) + ' || ' + str(fedsubavg_shares_b[idx]) \
              + ' || ' + str(fedsubavg_shares_my_ssk[idx])
        # Encrypt with AES_CBC
        enc_msg = AESCipher(str(sym_enc_key)).encrypt(msg)
        fedsubavg_ss_ciphers_dict[client_index] = enc_msg

        FEDSUBAVG_OTHERS_STORAGE[client_index]['sym_enc_key'] = sym_enc_key
        '''
        FEDSUBAVG_OTHERS_STORAGE[client_index]['msg'] = msg
        FEDSUBAVG_OTHERS_STORAGE[client_index]['enc_msg'] = enc_msg
        '''
    end_time_1 = time.time()

    # send encrypted shares to the server
    fedsubavg_ss_ciphers_send_message = {
        'client_ID': FEDSUBAVG_SELF_STORAGE['my_index'],
        'ss_ciphers': fedsubavg_ss_ciphers_dict
    }
    communication.send_np_array(fedsubavg_ss_ciphers_send_message,
                                client_socket)
    print(
        'Client %d sent encrypted secret shares to server in secure federated submodel averaging'
        % FEDSUBAVG_SELF_STORAGE['my_index'])
    sys.stdout.flush()

    # Receive other clients' encrypted shares and indices for mutual mask to me from the server
    round1_returned_message = communication.get_np_array(client_socket)
    print(
        "Received other clients' encrypted secret shares and indices for mutual mask from server"
    )
    sys.stdout.flush()

    start_time_2 = time.time()

    # Decrypt the secret shares and store them
    ss_ciphers_dict_received = round1_returned_message['ss_ciphers_dict']
    for client_index, enc_msg in ss_ciphers_dict_received.items():
        # Decrypt the encrypted message and parse it
        sym_enc_key = FEDSUBAVG_OTHERS_STORAGE[client_index]['sym_enc_key']
        msg = AESCipher(str(sym_enc_key)).decrypt(enc_msg)
        msg_parts = msg.split(' || ')
        # Sanity check
        from_client_index = int(msg_parts[0])
        my_index = int(msg_parts[1])
        assert from_client_index == client_index and my_index == FEDSUBAVG_SELF_STORAGE[
            'my_index']
        # Store secret shares of other clients
        FEDSUBAVG_OTHERS_STORAGE[client_index]['share_b'] = msg_parts[2]
        FEDSUBAVG_OTHERS_STORAGE[client_index]['share_ssk'] = msg_parts[3]
    # Indices of other clients (except myself) for mutual mask U1\Client Self
    FEDSUBAVG_SELF_STORAGE[
        'mutual_mask_general_client_indices'] = round1_returned_message[
            'mutual_mask_general_client_indices']

    end_time_2 = time.time()
    write_csv(FEDSUBAVG_SELF_STORAGE['client_computation_time_path'], [FEDSUBAVG_SELF_STORAGE['communication_round_number'], \
               "sfsa_U1", end_time_1 - start_time_1 + end_time_2 - start_time_2])
示例#9
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)
示例#10
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!')