def main(path, batch_id): # create the encryption keys skA, pkA = prio.create_keypair() skB, pkB = prio.create_keypair() # create the client cfg = prio.Config(N_DATA, pkA, pkB, bytes(batch_id, 'utf-8')) client = prio.Client(cfg) # generate test data data = generate(batch_id, client) with open(path, "w") as f: write(f, data) # print a command to use def clean(s): return s[:-1].decode('utf-8') args = { "--pings": path, "--pubkey-A": clean(pkA.export_hex()), "--pvtkey-A": clean(skA.export_hex()), "--pubkey-B": clean(pkB.export_hex()), "--pvtkey-B": clean(skB.export_hex()), } argstr = " \\".join([f"\n\t{k} {v}" for k, v in args.items()]) print(f"python main.py \\{argstr}")
async def run_client(pubkey_a, pubkey_b, n_clients, n_fields, batch_id): connection = await aio_pika.connect_robust("amqp://*****:*****@rabbitmq:5672/") channel = await connection.channel() await channel.declare_queue("prio.0") await channel.declare_queue("prio.1") # delay for server setup await asyncio.sleep(3) pkA = prio.PublicKey().import_hex(pubkey_a) pkB = prio.PublicKey().import_hex(pubkey_b) config = prio.Config(n_fields, pkA, pkB, batch_id) client = prio.Client(config) data_items = bytes([(i % 3 == 1) or (i % 5 == 1) for i in range(n_fields)]) for i in range(n_clients): logger.info("Client {}: Generated shares".format(i)) for_server_a, for_server_b = client.encode(data_items) await channel.default_exchange.publish( aio_pika.Message(body=for_server_a, message_id=str(i), type="data"), routing_key="prio.0", ) await channel.default_exchange.publish( aio_pika.Message(body=for_server_b, message_id=str(i), type="data"), routing_key="prio.1", ) await connection.close() logger.info("Client done!")
def test_client_agg(n_clients): seed = prio.PRGSeed() skA, pkA = prio.create_keypair() skB, pkB = prio.create_keypair() # the config is shared across all actors config = prio.Config(133, pkA, pkB, b"test_batch") sA = prio.Server(config, prio.PRIO_SERVER_A, skA, seed) sB = prio.Server(config, prio.PRIO_SERVER_B, skB, seed) client = prio.Client(config) n_data = config.num_data_fields() data_items = bytes([(i % 3 == 1) or (i % 5 == 1) for i in range(n_data)]) for i in range(n_clients): for_server_a, for_server_b = client.encode(data_items) # Setup verification vA = sA.create_verifier(for_server_a) vB = sB.create_verifier(for_server_b) # Produce a packet1 and send to the other party p1A = vA.create_verify1() p1B = vB.create_verify1() # Produce packet2 and send to the other party p2A = vA.create_verify2(p1A, p1B) p2B = vB.create_verify2(p1A, p1B) assert vA.is_valid(p2A, p2B) assert vB.is_valid(p2A, p2B) sA.aggregate(vA) sB.aggregate(vB) t_a = sA.total_shares() t_b = sB.total_shares() output = prio.total_share_final(config, t_a, t_b) expected = [item * n_clients for item in list(data_items)] assert (list(output) == expected)
async def main(): n_clients = 10 n_data = 133 server_secret = prio.PRGSeed() skA, pkA = prio.create_keypair() skB, pkB = prio.create_keypair() cfg = prio.Config(n_data, pkA, pkB, b"test_batch") sA = prio.Server(cfg, prio.PRIO_SERVER_A, skA, server_secret) sB = prio.Server(cfg, prio.PRIO_SERVER_B, skB, server_secret) data_items = bytes([(i % 3 == 1) or (i % 5 == 1) for i in range(n_data)]) logger.info("Starting asyncio prio pipeline.") client = prio.Client(cfg) queue_a = asyncio.Queue() queue_b = asyncio.Queue() await client_produce(client, data_items, queue_a, queue_b, n_clients) consumers = asyncio.ensure_future( asyncio.gather( server_consume(sA, queue_a, queue_b), server_consume(sB, queue_b, queue_a), )) await asyncio.gather(queue_a.join(), queue_b.join()) t_a = sA.total_shares() t_b = sB.total_shares() output = prio.total_share_final(cfg, t_a, t_b) expected = [item * n_clients for item in list(data_items)] assert (list(output) == expected) consumers.cancel() logger.info("Done!")
# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. from prio import prio import sys skA, pkA = prio.create_keypair() skB, pkB = prio.create_keypair() n_data = 133 batch_id = b"test_batch" cfg = prio.Config(n_data, pkA, pkB, batch_id) server_secret = prio.PRGSeed() sA = prio.Server(cfg, prio.PRIO_SERVER_A, skA, server_secret) sB = prio.Server(cfg, prio.PRIO_SERVER_B, skB, server_secret) client = prio.Client(cfg) data_items = bytes([(i % 3 == 1) or (i % 5 == 1) for i in range(n_data)]) for_server_a, for_server_b = client.encode(data_items) # Setup verification vA = sA.create_verifier(for_server_a) vB = sB.create_verifier(for_server_b) # Produce a packet1 and send to the other party p1A = vA.create_verify1() p1B = vB.create_verify1()
def init_servers(build_id): # The pilot includes 3 boolean histograms config = prio.Config(3, pkA, pkB, bytes(build_id, "utf-8")) server_a = prio.Server(config, prio.PRIO_SERVER_A, skA, server_secret) server_b = prio.Server(config, prio.PRIO_SERVER_B, skB, server_secret) return config, server_a, server_b
async def run_server(pubkey, pvtkey, pubkey_other, server_id, n_fields, batch_id, shared_seed): connection = await aio_pika.connect_robust( "amqp://*****:*****@rabbitmq:5672/") channel = await connection.channel() queue = await channel.declare_queue(f"prio.{server_id}") pk = prio.PublicKey().import_hex(pubkey) sk = prio.PrivateKey().import_hex(pvtkey, pubkey) pk_other = prio.PublicKey().import_hex(pubkey_other) seed = prio.PRGSeed() seed.instance = shared_seed config = prio.Config(n_fields, pk, pk_other, batch_id) server = prio.Server(config, server_id, sk, seed) cache = {} async for message in queue: with message.process(): pid = message.message_id v, p1, p2 = cache.get(pid, (None, None, None)) def log(line): logger.info("Message {}: {}".format(pid, line)) ptype = message.type routing_key = "prio.{}".format(get_other_server(server_id)) if (ptype == "verify1" and not p1) or (ptype == "verify2" and not p2): log("Re-queuing message!") await channel.default_exchange.publish( aio_pika.Message( body=message.body, message_id=message.message_id, type=message.type, ), routing_key="prio.{}".format(server_id), ) elif ptype == "data": log("Generating verify packet 1") v = server.create_verifier(message.body) p1 = v.create_verify1() await channel.default_exchange.publish( aio_pika.Message( body=pickle.dumps(p1), message_id=message.message_id, type="verify1", ), routing_key=routing_key, ) elif ptype == "verify1": log("Generating verify packet 2") p2 = v.create_verify2(p1, pickle.loads(message.body)) await channel.default_exchange.publish( aio_pika.Message( body=pickle.dumps(p2), message_id=message.message_id, type="verify2", ), routing_key=routing_key, ) elif ptype == "verify2": if v.is_valid(p2, pickle.loads(message.body)): log("Aggregate data") server.aggregate(v) else: log("Invalid data") del cache[pid] else: log("Bad message type {}".format(ptype)) cache[pid] = (v, p1, p2)
def config(serverA_keypair, serverB_keypair): _, pkA = serverA_keypair _, pkB = serverB_keypair return prio.Config(133, pkA, pkB, b"test_batch")