Пример #1
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])
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])
Пример #3
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)
Пример #4
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)