def server_ack(OK, msg): if OK: pass #print_success(msg, CLIENT_VALUES['my_sid']) else: print_failure(msg, CLIENT_VALUES['my_sid']) sio.disconnect()
def handle_encrypted_messages(encrypted_messages): sending_client_sid = request.sid # Check in which round the FSM is if SERVER_VALUES['ROUND'] != 1: print_failure('Too late to send list of encrypted messages.', sending_client_sid) return False, 'Too late to send your list encrypted messages.' # If False, make this node drop (sio.disconnect()) in the client callback # TODO: Verify assumptions about this list and about sending_client_sid # Add the list of encrypted messages from this client SID to the Server Storage ########################################## SERVER_STORAGE[sending_client_sid]['list_enc_msg'] = encrypted_messages ############################################# # Logging message #print_success('Received list of encrypted messages.', sending_client_sid) # Add this client SID in the list of active clients at round 1 SERVER_VALUES['U1'].append(sending_client_sid) # No clients from last round have dropped out, and this is the last client we're receiving the list of encrypted messages from if set(SERVER_VALUES['U1']) == set(SERVER_VALUES['U0']): SERVER_VALUES['BENCHMARK_TIME_ROUND_1_COMM'] = time.time( ) - SERVER_VALUES['starting_time_round_1'] print('Received all encrypted msgs', SERVER_VALUES['BENCHMARK_TIME_ROUND_1_COMM']) # Acknowledgement message (to the client) that everything went fine return True, 'List of encrypted messages succesfully received by server.'
def handle_shares(shares): sending_client_sid = request.sid # Check in which round the FSM is if SERVER_VALUES['ROUND'] != 3: print_failure('Too late to send final shares.', sending_client_sid) return False, 'Too late to send your mask and shares.' # If False, make this node drop (sio.disconnect()) in the client callback # TODO: Verify assumptions about this y (format etc...) # Add the shares from this client SID to the Server Storage #################################################################################### SERVER_STORAGE[sending_client_sid]['b_shares_alive'] = shares[ 'b_shares_alive'] SERVER_STORAGE[sending_client_sid]['ssk_shares_dropped'] = shares[ 'ssk_shares_dropped'] #################################################################################### # Logging message #print_success('Received share of mask "b" for alive clients and share of key "ssk" for dropped out clients.', request.sid) # Add this client SID in the list of active clients at round 3 SERVER_VALUES['U3'].append(sending_client_sid) # No clients from last round have dropped out, and this is the last client we're receiving the masked input y from if set(SERVER_VALUES['U3']) == set(SERVER_VALUES['U2']): SERVER_VALUES['BENCHMARK_TIME_ROUND_3_COMM'] = time.time( ) - SERVER_VALUES['starting_time_round_3'] print('Received all shares/masks', SERVER_VALUES['BENCHMARK_TIME_ROUND_3_COMM']) return True, 'Shares succesfully received by server.'
def round2(): U2 = SERVER_VALUES['U2'] n2 = len(U2) if n2 < SERVER_VALUES['t']: print_failure( 'Did not receive masked input "y" 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 U1 but not in U2 dropped_out_clients = list(set(SERVER_VALUES['U1']) - set(U2)) SERVER_VALUES['dropped_out_clients_round_2'] = dropped_out_clients #print() #print_info('Advertise list of alive and dropped out clients from the previous round to all still alive clients.', 'Server') #print() sio.emit('ROUND_3', {'dropped_out': dropped_out_clients, 'alive': U2}) sio.start_background_task(timer_round_3)
def round0(): U0 = SERVER_VALUES['U0'] n0 = len(U0) if n0 < 2: # At least 3 clients (n=3, t=2) print_failure( 'Did not receive public keys 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 SERVER_VALUES['n0'] = n0 SERVER_VALUES['t'] = int(n0 / 2) + 1 list_pubkeys = { } # Copy here the cpk and spk keys for each client, don't send the WHOLE server storage dict for client_sid in U0: list_pubkeys[client_sid] = {} list_pubkeys[client_sid]['cpk'] = SERVER_STORAGE[client_sid]['cpk'] list_pubkeys[client_sid]['spk'] = SERVER_STORAGE[client_sid]['spk'] #print() #print_info('Broadcasting list of pubkeys to clients.', 'Server') #print() sio.emit( 'ROUND_1', list_pubkeys) # No callback because it's a broadcast message (room=/) sio.start_background_task(timer_round_1)
def handle_y(y): sending_client_sid = request.sid # Check in which round the FSM is if SERVER_VALUES['ROUND'] != 2: print_failure('Too late to send masked input "y".', sending_client_sid) return False, 'Too late to send your masked input "y".' # If False, make this node drop (sio.disconnect()) in the client callback # TODO: Verify assumptions about this y (format etc...) # Add the masked input y from this client SID to the Server Storage ############################################################ SERVER_STORAGE[sending_client_sid]['y'] = y ############################################################ # Logging message #print_success('Received masked input "y".', request.sid) # Add this client SID in the list of active clients at round 2 SERVER_VALUES['U2'].append(sending_client_sid) # No clients from last round have dropped out, and this is the last client we're receiving the masked input y from if set(SERVER_VALUES['U2']) == set(SERVER_VALUES['U1']): SERVER_VALUES['BENCHMARK_TIME_ROUND_2_COMM'] = time.time( ) - SERVER_VALUES['starting_time_round_2'] print('Received all inputs y', SERVER_VALUES['BENCHMARK_TIME_ROUND_2_COMM']) # Acknowledgement message (to the client) that everything went fine return True, 'Masked input "y" succesfully received by server.'
def classify(self, exercise, key, X, verbose=False): try: prediction = self.classifiers[exercise][key].predict(X) if verbose: ut.print_success(key + ': reps classified') return prediction except Exception as e: print e ut.print_failure(key + ': reps not classified') return None
def round1(): U1 = SERVER_VALUES['U1'] n1 = len(U1) #print(U1) print("|U1| the number of clients sending enc mesage:", n1) #print(SERVER_VALUES['t']) if n1 < SERVER_VALUES['t']: print_failure( 'Did not receive encrypted messages 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 U0 but not in U1 dropped_out_clients = list(set(SERVER_VALUES['U0']) - set(U1)) SERVER_VALUES['dropped_out_clients_round_1'] = dropped_out_clients # Instead of having a dictionary of messages FROM a given client SID, we want to construct # a dictionary of messages TO a given client SID. list_enc_msg_FROM = {} for client_sid in U1: list_enc_msg_FROM[client_sid] = SERVER_STORAGE[client_sid][ 'list_enc_msg'] # This is here that we reverse the "FROM key TO value" dict to a "FROM value TO key" dict # e.g: {1: {2:a, 3:b, 4:c}, 3: {1:d,2:e,4:f}, 4: {1:g,2:h,3:i}} --> {1: {3:d, 4:g}, 3:{1:b, 4:i}, 4: {1:c,3:f} } list_enc_msg_TO = {} for from_client_sid, enc_msg_from_client_sid in list_enc_msg_FROM.items(): for to_client_sid, enc_msg_to_client_sid in enc_msg_from_client_sid.items( ): # print(from_client_sid + ' --> ' + to_client_sdropoutid + ' : ' + str(enc_msg_to_client_sid)) list_enc_msg_TO.setdefault( to_client_sid, {})[from_client_sid] = enc_msg_to_client_sid #print_info('Forwarding lists of encrypted messages to all clients.', 'Server') sessionID = SERVER_VALUES['sessionID'] #print("sessionID------->",sessionID) serverround1totalsize = 0 for client_sid in U1: round1servertoclientmessages = { "SID": sessionID, "enc_msgs": list_enc_msg_TO[client_sid] } serverround1totalsize += total_size(round1servertoclientmessages) sio.emit('ROUND_2', round1servertoclientmessages, room=client_sid) SERVER_VALUES['serverround1totalsize'] = serverround1totalsize #单播 逐个相加 sio.start_background_task(timer_round_2)
def classify(self, exercise, key, X, verbose=True): try: # temp =cf.train_squat_classifiers(exercise) # prediction=temp[key].predict(X) prediction = self.classifiers[exercise][key].predict(X) if verbose: ut.print_success(key + ': classified') return prediction except Exception as e: print(e) ut.print_failure(key + ': not classified') return None
def round2(): U2 = SERVER_VALUES['U2'] n2 = len(U2) print("|U2| the number of clients sending inputs y:", n2) if n2 < SERVER_VALUES['t']: print_failure( 'Did not receive masked input "y" 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 U1 but not in U2 dropped_out_clients = list(set(SERVER_VALUES['U1']) - set(U2)) SERVER_VALUES['dropped_out_clients_round_2'] = dropped_out_clients #print() #print_info('Advertise list of alive and dropped out clients from the previous round to all still alive clients.', 'Server') #print() round2servertoclientmessages = [] for client_sid in U2: round2clienttoservermessages = SERVER_STORAGE[client_sid][ 'round2clienttoservermessages'] round2servertoclientmessages.append(round2clienttoservermessages) SERVER_VALUES['serverround2totalsize'] = total_size({ 'dropped_out': dropped_out_clients, 'alive': U2, 'round2servertoclientmessages': round2servertoclientmessages }) sio.emit( 'ROUND_3', { 'dropped_out': dropped_out_clients, 'alive': U2, 'round2servertoclientmessages': round2servertoclientmessages }) sio.start_background_task(timer_round_3)
def handle_y(round2clienttoservermessages): sending_client_sid = request.sid #store the messages received from clients SERVER_STORAGE[sending_client_sid][ 'round2clienttoservermessages'] = round2clienttoservermessages # Check in which round the FSM is if SERVER_VALUES['ROUND'] != 2: print_failure('Too late to send masked input "y".', sending_client_sid) return False, 'Too late to send your masked input "y".' # If False, make this node drop (sio.disconnect()) in the client callback # TODO: Verify assumptions about this y (format etc...) # Add the masked input y from this client SID to the Server Storage ############################################################ SERVER_STORAGE[sending_client_sid]['y'] = round2clienttoservermessages[ "mask_x"] ############################################################ # Logging message #print_success('Received masked input "y".', request.sid) # Add this client SID in the list of active clients at round 2 SERVER_VALUES['U2'].append(sending_client_sid) # No clients from last round have dropped out, and this is the last client we're receiving the masked input y from #10.15 when note the communication cost of round 2 when clients dropping out, #we should let the condition len(SERVER_VALUES['U2']) == constant ,where constant = N *( 1 - drop_out) #modify for drouout #if set(SERVER_VALUES['U2']) == set(SERVER_VALUES['U1']): if len(SERVER_VALUES['U2']) == int( len(SERVER_VALUES['U1']) * (1 - dropout)): SERVER_VALUES['BENCHMARK_TIME_ROUND_2_COMM'] = time.time( ) - SERVER_VALUES['starting_time_round_2'] print('Received all inputs y', SERVER_VALUES['BENCHMARK_TIME_ROUND_2_COMM']) # Acknowledgement message (to the client) that everything went fine return True, 'Masked input "y" succesfully received by server.'
def handle_pubkeys(data): sending_client_sid = request.sid #io客户端的sid, socketio用此唯一标识客户端. # Check in which round the FSM is if SERVER_VALUES['ROUND'] != 0: print_failure('Too late to send public keys.', sending_client_sid) return False, 'Too late to send your public keys.' # If False, make this node drop (sio.disconnect()) in the client callback # Add public key cpk to Server Storage for this client SID try: SERVER_STORAGE.setdefault(sending_client_sid, {})['cpk'] = data['cpk'] except: print_failure('Missing key cpk in client' 's messsage.', sending_client_sid) return False, 'Missing key cpk in your message.' # Add public key spk to Server Storage for this client SID try: SERVER_STORAGE.setdefault(sending_client_sid, {})['spk'] = data['spk'] except: print_failure('Missing key spk in client' 's messsage.', sending_client_sid) return False, 'Missing key spk in your message.' # Logging message #print_success('Received public keys.', sending_client_sid) # Add this client SID in the list of active clients at round 0 SERVER_VALUES['U0'].append(sending_client_sid) # No clients have dropped out so far, and this is the last client we're receiving the public keys from if len(set(SERVER_VALUES['U0'])) == INIT_NB_CLIENTS: SERVER_VALUES['BENCHMARK_TIME_ROUND_0_COMM'] = time.time( ) - SERVER_VALUES['starting_time_round_0'] print('Received all pubkeys', SERVER_VALUES['BENCHMARK_TIME_ROUND_0_COMM']) # Acknowledgement message (to the client) that everything went fine return True, 'Public keys succesfully received by server.'
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
pt = PersonalTrainer({'squat': 'NeckY', 'pushup': 'NeckY'}) try: #pt.load_reps('squat',os.path.join('../data/data_sets','multipleClass4.p')) pt.load_reps('pushup', os.path.join('../data/data_sets', 'pushupDataSet109.p')) # pt.load_reps(os.path.join('../data/data_sets','pushupDataSet109.p')) ut.print_success('Training data loaded') try: #pt.set_classifiers('squat',classification_ftopt.train_squat_classifiers(pt)) pt.set_classifiers('pushup', classification_ftopt.train_pushup_classifiers(pt)) # pt.set_classifiers(classification.train_pushup_classifiers(pt)) ut.print_success('Classifiers trained') except Exception as e: ut.print_failure('Could not train classifiers' + str(e)) except Exception as e: ut.print_failure('Could not load training data:' + str(e)) # #Store Classifiers # In[ ]: # # classifiers = pt.get_classifiers('squat') # pickle.dump(classifiers,open('squat_classifiers_ftopt.p','wb')) classifiers = pt.get_classifiers('pushup') pickle.dump(classifiers, open('pushup_classifiers_ftopt.p', 'wb')) # In[ ]:
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)
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!')
def abort(reason): print() print_failure(reason, 'Server') sio.disconnect()
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)
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 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