main.rs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. use std::env;
  2. use std::time::Instant;
  3. use rand::RngCore;
  4. use spiral_spir::client::Client;
  5. use spiral_spir::init;
  6. use spiral_spir::server::Server;
  7. fn main() {
  8. let args: Vec<String> = env::args().collect();
  9. if args.len() < 2 || args.len() > 5 {
  10. println!(
  11. "Usage: {} r [num_threads [num_preproc [num_pirs]]]\nr = log_2(num_records)",
  12. args[0]
  13. );
  14. return;
  15. }
  16. let r: usize = args[1].parse().unwrap();
  17. let mut num_threads = 1usize;
  18. let mut num_preproc = 1usize;
  19. let num_pirs: usize;
  20. if args.len() > 2 {
  21. num_threads = args[2].parse().unwrap();
  22. }
  23. if args.len() > 3 {
  24. num_preproc = args[3].parse().unwrap();
  25. }
  26. if args.len() > 4 {
  27. num_pirs = args[4].parse().unwrap();
  28. } else {
  29. num_pirs = num_preproc;
  30. }
  31. let num_records = 1 << r;
  32. let num_records_mask = num_records - 1;
  33. println!("===== ONE-TIME SETUP =====\n");
  34. let otsetup_start = Instant::now();
  35. init(num_threads);
  36. let (client, pub_params) = Client::new(r);
  37. let pub_params_len = pub_params.len();
  38. let server = Server::new(r, pub_params);
  39. let otsetup_us = otsetup_start.elapsed().as_micros();
  40. println!("One-time setup: {} µs", otsetup_us);
  41. println!("pub_params len = {}", pub_params_len);
  42. println!("\n===== PREPROCESSING =====\n");
  43. println!("num_preproc = {}", num_preproc);
  44. let preproc_client_start = Instant::now();
  45. let preproc_msg = client.preproc(num_preproc);
  46. let preproc_client_us = preproc_client_start.elapsed().as_micros();
  47. println!("Preprocessing client: {} µs", preproc_client_us);
  48. println!("preproc_msg len = {}", preproc_msg.len());
  49. let preproc_server_start = Instant::now();
  50. let preproc_resp = server.preproc_process(&preproc_msg);
  51. let preproc_server_us = preproc_server_start.elapsed().as_micros();
  52. println!("Preprocessing server: {} µs", preproc_server_us);
  53. println!("preproc_resp len = {}", preproc_resp.len());
  54. let preproc_finish_start = Instant::now();
  55. client.preproc_finish(&preproc_resp);
  56. let preproc_finish_us = preproc_finish_start.elapsed().as_micros();
  57. println!("Preprocessing client finish: {} µs", preproc_finish_us);
  58. let mut rng = rand::thread_rng();
  59. for i in 1..num_pirs + 1 {
  60. println!("\n===== SPIR QUERY {} =====\n", i);
  61. let idx = (rng.next_u64() as usize) & num_records_mask;
  62. let query_client_start = Instant::now();
  63. let query_msg = client.query(idx);
  64. let query_client_us = query_client_start.elapsed().as_micros();
  65. println!("Query client: {} µs", query_client_us);
  66. println!("query_msg len = {}", query_msg.len());
  67. }
  68. /*
  69. let spiral_params = params::get_spiral_params(r);
  70. let mut rng = rand::thread_rng();
  71. print_params_summary(&spiral_params);
  72. println!("OT one-time setup: {} µs", otsetup_us);
  73. // One-time setup for the Spiral client
  74. let spc_otsetup_start = Instant::now();
  75. let mut clientrng = rand::thread_rng();
  76. let mut client = Client::init(&spiral_params, &mut clientrng);
  77. let pub_params = client.generate_keys();
  78. let pub_params_buf = pub_params.serialize();
  79. let spc_otsetup_us = spc_otsetup_start.elapsed().as_micros();
  80. let spiral_blocking_factor = spiral_params.db_item_size / mem::size_of::<DbEntry>();
  81. println!(
  82. "Spiral client one-time setup: {} µs, {} bytes",
  83. spc_otsetup_us,
  84. pub_params_buf.len()
  85. );
  86. println!("\n===== PREPROCESSING =====\n");
  87. // Spiral preprocessing: create a PIR lookup for an element at a
  88. // random location
  89. let spc_query_start = Instant::now();
  90. let rand_idx = (rng.next_u64() as usize) % num_records;
  91. let rand_pir_idx = rand_idx / spiral_blocking_factor;
  92. println!("rand_idx = {} rand_pir_idx = {}", rand_idx, rand_pir_idx);
  93. let spc_query = client.generate_query(rand_pir_idx);
  94. let spc_query_buf = spc_query.serialize();
  95. let spc_query_us = spc_query_start.elapsed().as_micros();
  96. println!(
  97. "Spiral query: {} µs, {} bytes",
  98. spc_query_us,
  99. spc_query_buf.len()
  100. );
  101. // Create the database encryption keys and do the OT to fetch the
  102. // right one, but don't actually encrypt the database yet
  103. let dbkeys = gen_db_enc_keys(r);
  104. let otkeyreq_start = Instant::now();
  105. let (keystate, keyquery) = otkey_request(rand_idx, r);
  106. let keyquerysize = keyquery.len() * keyquery[0].len();
  107. let otkeyreq_us = otkeyreq_start.elapsed().as_micros();
  108. let otkeysrv_start = Instant::now();
  109. let keyresponse = otkey_serve(keyquery, &dbkeys);
  110. let keyrespsize = keyresponse.len() * keyresponse[0].len();
  111. let otkeysrv_us = otkeysrv_start.elapsed().as_micros();
  112. let otkeyrcv_start = Instant::now();
  113. let otkey = otkey_receive(keystate, &keyresponse);
  114. let otkeyrcv_us = otkeyrcv_start.elapsed().as_micros();
  115. println!("key OT query in {} µs, {} bytes", otkeyreq_us, keyquerysize);
  116. println!("key OT serve in {} µs, {} bytes", otkeysrv_us, keyrespsize);
  117. println!("key OT receive in {} µs", otkeyrcv_us);
  118. // Create a database with recognizable contents
  119. let db: Vec<DbEntry> = ((0 as DbEntry)..(num_records as DbEntry))
  120. .map(|x| 10000001 * x)
  121. .collect();
  122. println!("\n===== RUNTIME =====\n");
  123. // Pick the record we actually want to query
  124. let q = (rng.next_u64() as usize) % num_records;
  125. // Compute the offset from the record index we're actually looking
  126. // for to the random one we picked earlier. Tell it to the server,
  127. // who will rotate right the database by that amount before
  128. // encrypting it.
  129. let idx_offset = (num_records + rand_idx - q) % num_records;
  130. println!("Send to server {} bytes", 8 /* sizeof(idx_offset) */);
  131. // The server rotates, blinds, and encrypts the database
  132. let blind: DbEntry = 20;
  133. let encdb_start = Instant::now();
  134. let encdb = encdb_xor_keys(&db, &dbkeys, r, idx_offset, blind, num_threads);
  135. let encdb_us = encdb_start.elapsed().as_micros();
  136. println!("Server encrypt database {} µs", encdb_us);
  137. // Load the encrypted database into Spiral
  138. let sps_loaddb_start = Instant::now();
  139. let sps_db = load_db_from_slice_mt(&spiral_params, &encdb, num_threads);
  140. let sps_loaddb_us = sps_loaddb_start.elapsed().as_micros();
  141. println!("Server load database {} µs", sps_loaddb_us);
  142. // Do the PIR query
  143. let sps_query_start = Instant::now();
  144. let sps_query = Query::deserialize(&spiral_params, &spc_query_buf);
  145. let sps_response = process_query(&spiral_params, &pub_params, &sps_query, sps_db.as_slice());
  146. let sps_query_us = sps_query_start.elapsed().as_micros();
  147. println!(
  148. "Server compute response {} µs, {} bytes (*including* the above expansion time)",
  149. sps_query_us,
  150. sps_response.len()
  151. );
  152. // Decode the response to yield the whole Spiral block
  153. let spc_recv_start = Instant::now();
  154. let encdbblock = client.decode_response(sps_response.as_slice());
  155. // Extract the one encrypted DbEntry we were looking for (and the
  156. // only one we are able to decrypt)
  157. let entry_in_block = rand_idx % spiral_blocking_factor;
  158. let loc_in_block = entry_in_block * mem::size_of::<DbEntry>();
  159. let loc_in_block_end = (entry_in_block + 1) * mem::size_of::<DbEntry>();
  160. let encdbentry = DbEntry::from_le_bytes(
  161. encdbblock[loc_in_block..loc_in_block_end]
  162. .try_into()
  163. .unwrap(),
  164. );
  165. let decdbentry = otkey_decrypt(&otkey, rand_idx, encdbentry);
  166. let spc_recv_us = spc_recv_start.elapsed().as_micros();
  167. println!("Client decode response {} µs", spc_recv_us);
  168. println!("index = {}, Response = {}", q, decdbentry);
  169. */
  170. }