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)
# 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() sk2, pk2 = DHKE.generate_keys() shared_key = DHKE.agree(sk1, pk2) shared_key2 = DHKE.agree(sk2, pk1) assert shared_key == shared_key2 # TODO: Use KDF to generate AES key sender = OT_Sender('Dentifrice', 'Laboratoire') receiver = OT_Receiver(1) A = sender.generate_A() # print('A =', A) B = receiver.generate_B(A) # print('B =', B) e0, e1 = sender.generate_e0_e1(B) # print('e0 =', e0)
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
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
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 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!')