def test_tiny_circuit(): t = 2 n = 5 c_path = "circuits/tiny_circuit.txt" triples = gen_triples(t, n, 2) mq = Queue() queues = [Queue() for _ in range(n)] x = '01' y = '10' result = '11' x_shares = Shamir(t, n).share_bitstring_secret(x) y_shares = Shamir(t, n).share_bitstring_secret(y) processes = [] for i in range(n): p = Process(target=run_circuit_process, args=(t, n, c_path, i + 1, queues, mq, x_shares[i] + y_shares[i], triples[i])) processes.append(p) for p in processes: p.start() vals = [] while len(vals) < n: if not mq.empty(): vals.append(mq.get()) reconstructed = Shamir(t, n).reconstruct_bitstring_secret(vals) print("result:", reconstructed) assert reconstructed == result, "result incorrect" print("TEST PASSED") for p in processes: p.join() for q in queues: q.close() q.join_thread() mq.close() mq.join_thread()
def gen_triples(t, n, n_triples): triples = [[] for _ in range(n)] for i in range(n_triples): a = randelement() b = randelement() c = a * b a_shares = Shamir(t, n).share_secret(a) b_shares = Shamir(t, n).share_secret(b) c_shares = Shamir(t, n).share_secret(c) for i in range(n): triples[i].append( TripleShare(a_shares[i], b_shares[i], c_shares[i])) return triples
def consumer(mq, t, n, processes): vals = [] while len(vals) < n: if not mq.empty(): vals.append(mq.get()) n_triples = len(vals[0]) for i in [0, 1, n_triples - 2, n_triples - 1]: trips = [vals[j][i] for j in range(n)] a_shares = [t.a for t in trips] b_shares = [t.b for t in trips] c_shares = [t.c for t in trips] a = Shamir(t, n).reconstruct_secret(a_shares) b = Shamir(t, n).reconstruct_secret(b_shares) c = Shamir(t, n).reconstruct_secret(c_shares) assert a * b == c, "triples are not equal"
def share_secret(self): shaTSS = Shamir(self.t, self.n) self.p, alpha = shaTSS.GC(_sage_const_128) shares = shaTSS.DS(self.p, alpha, self.members[_sage_const_0].k) for i in range(_sage_const_1, self.n + _sage_const_1): self.members[i].shares = shares[i - _sage_const_1] print('sended shaTSS')
def gen_threshold_sign(self, h, m, s, shares): shaTSS = Shamir(self.t, self.n) k = shaTSS.SC(self.p, shares).list()[_sage_const_0] kk = bin(int(str(k)))[_sage_const_2:] R = m.parent() f_len = int(kk[:_sage_const_8], _sage_const_2) fs_len = int(kk[_sage_const_8:_sage_const_16], _sage_const_2) R = m.parent() f = R([ -_sage_const_1 * int(x) for x in kk[_sage_const_16:_sage_const_16 + f_len] ]) fs = R([ -_sage_const_1 * int(x) for x in kk[_sage_const_16 + f_len:_sage_const_16 + f_len + fs_len] ]) x = auxmath.normilize_coeffs(-(_sage_const_1 / self.q) * m * fs) y = auxmath.normilize_coeffs(-(_sage_const_1 / self.q) * m * f) s0 = x * f + y * fs s_res = R(s + s0) b = s_res * auxmath.normilize_coeffs2(s_res * self.h0 - m, self.q) print(b) print(b.norm(_sage_const_2))
def test_mpc(t, n, c_path, n_triples, inputs, result, reflect=False): triples = gen_triples(t, n, n_triples) mq = Queue() queues = [Queue() for _ in range(n)] share_inputs = [Shamir(t, n).share_bitstring_secret(i) for i in inputs] processes = [] for i in range(n): inputs = [] for si in share_inputs: inputs.extend(si[i]) p = Process(target=run_circuit_process, args=(t, n, c_path, i+1, queues, mq, inputs, triples[i])) processes.append(p) start = time.time() for p in processes: p.start() t1 = Thread(target=consumer, args=(mq, n, result, t, processes, reflect)) t1.start() for p in processes: if p.is_alive(): p.join() t1.join(n) print(f"time: {round(time.time()-start, 4)} seconds") for q in queues: q.close() q.join_thread() mq.join_thread()
def test_reconstruction(): t = 2 n = 2*t+1 shamir = Shamir(t, n) secret = randelement() shares = shamir.share_secret(secret) reconstructed = shamir.reconstruct_secret(shares[:t+1]) assert secret == reconstructed, "reconstructed the wrong value"
async def eval_circuit(t, n, c, index, queues, main_queue, inputs, triples): shamir = Shamir(t, n) dispatcher = Dispatcher(t, n, index, queues, "--UNIQUE COMPUTATION ID--") outputs = await c.evaluate(inputs, shamir=shamir, dispatcher=dispatcher, triples=triples) main_queue.put(outputs)
def share_secret(self): self.k = _sage_const_2048 self.shaTSS = Shamir(self.t, self.n) self.p, alpha = self.shaTSS.GC(self.k) print ('k ' + str(self.members[_sage_const_0 ].k)) shares = self.shaTSS.DS(self.p, alpha, self.members[_sage_const_0 ].k) for i in range(_sage_const_1 , self.n+_sage_const_1 ): self.members[i].shares = shares[i-_sage_const_1 ] self.members[i].alpha = shares[i-_sage_const_1 ][_sage_const_0 ] print ('secret generated')
def _testShamir(self, minimum, shares, prime, secret): if self.debug >= 10: print("testShamir(minimum=%d,shares=%d,prime=%d,secret=%d)" % (minimum, shares, prime, secret)) shamir = Shamir(minimum, prime) shamir.setSecret(secret) shamir.randomizeKeys(shares, self.rng) keys = [shamir.getKey(i) for i in range(1, shares + 1)] for t in range(100): self._testShamirRecover(minimum, shares, prime, secret, keys)
def test_mul32_circuit(): t = 2 n = 5 c_path = "circuits/mul32_circuit.txt" triples = gen_triples(t, n, 8000) mq = Queue() queues = [Queue() for _ in range(n)] x = 101 y = 50000 result = x * y x_bin = bin(x)[2:] while len(x_bin) < 32: x_bin = '0' + x_bin y_bin = bin(y)[2:] while len(y_bin) < 32: y_bin = '0' + y_bin x_shares = Shamir(t, n).share_bitstring_secret(x_bin) y_shares = Shamir(t, n).share_bitstring_secret(y_bin) processes = [] for i in range(n): p = Process(target=run_circuit_process, args=(t, n, c_path, i + 1, queues, mq, x_shares[i] + y_shares[i], triples[i])) processes.append(p) for p in processes: p.start() vals = [] while len(vals) < n: if not mq.empty(): vals.append(mq.get()) reconstructed = Shamir(t, n).reconstruct_bitstring_secret(vals) print("result:", reconstructed) assert eval('0b' + reconstructed) == result, "result incorrect" print("TEST PASSED") # TO DO: These processes aren't properly closing, so the test stalls here... # Probably something to do with some processes being locked/stalled? for p in processes: p.join() for q in queues: q.close() q.join_thread() mq.close() mq.join_thread()
def test_triple_creation(t, n, n_triples): shamir = Shamir(t, n) ## ## ROUND 1 ## player_ab_lists = [[] for _ in range(n)] # Each party for _ in range(n): # computes random shared values ab_lists = shamir.generate_triples_round_1(n_triples) # sends each other party their particular shares (point to point) for i in range(n): player_ab_lists[i].append(ab_lists[i]) ## ## ROUND 2 ## player_a_shares = [] player_b_shares = [] player_c_share_shares = [[] for _ in range(n)] # Each party for i in range(n): # collects received ab_list messages and computes intermediate values a_shares, b_shares, c_share_shares = shamir.generate_triples_round_2( player_ab_lists[i]) player_a_shares.append(a_shares) player_b_shares.append(b_shares) # sends each party their c_share_shares (point to point) for j in range(n): player_c_share_shares[j].append(c_share_shares[j]) ## ## ROUND 3 ## player_triples = [] # Each party for i in range(n): # collects received c_share_share messages and computes the result TripleShare values. triples = shamir.generate_triples_round_3(player_a_shares[i], player_b_shares[i], player_c_share_shares[i]) player_triples.append(triples) ## Check for i in range(len(player_triples[0])): check_a = shamir.reconstruct_secret([p[i].a for p in player_triples]) check_b = shamir.reconstruct_secret([p[i].b for p in player_triples]) check_c = shamir.reconstruct_secret([p[i].c for p in player_triples]) assert check_a * check_b == check_c, "invalid triple was created" return player_triples
def run_triplegen_process(t, n, index, queues, main_queue, batch_size, n_batches): shamir = Shamir(t, n) dispatcher = Dispatcher(t, n, index, queues, "") tg = TripleGeneration(index, shamir, dispatcher, batch_size=batch_size, n_batches=n_batches) tg.run() main_queue.put(tg.triples)
def consumer(mq, n, result, t, processes, reflect): vals = [] while len(vals) < n: if not mq.empty(): vals.append(mq.get()) reconstructed = Shamir(t, n).reconstruct_bitstring_secret(vals)[::-1] if reflect: reconstructed = reconstructed[ int(len(reconstructed) / 2):] + reconstructed[:int(len(reconstructed) / 2)] assert eval('0b' + reconstructed) == eval('0b' + result), "result incorrect"
def test_mul2_circuit(): t = 2 n = 5 c_path = "bristol_circuits/mul2.txt" n_triples = 2 for x, y in [(0, 1), (0, 0), (1, 1)]: result = (x * y) result = bin(result)[2:] x_bin = bin(x)[2:] y_bin = bin(y)[2:] inputs = Shamir(t, n).share_bitstring_secret(x_bin + y_bin) test_mpc(t, n, c_path, n_triples, inputs, result)
def run_circuit_process(t, n, c_path, index, queues, main_queue, inputs, triples): print(f"starting node {index}") shamir = Shamir(t, n) messenger = MockMessenger(t, n, index, queues) c = Circuit(c_path) outputs = c.evaluate(inputs, shamir=shamir, messenger=messenger, triples=triples) main_queue.put(outputs) print(f"closing node {index}")
async def operation(self, x, y, uuid): bx = bin(x)[2:] while len(bx) < 31: bx = '0' + bx x_shares = Shamir(self.t, self.n).share_bitstring_secret(bx[::-1]) by = bin(y)[2:] while len(by) < 31: by = '0' + by y_shares = Shamir(self.t, self.n).share_bitstring_secret(by[::-1]) tasks = [] for k, v in self.idx2node.items(): msg = {'uuid': uuid, 'x_inputs': serialize_shares(x_shares[k-1]), 'y_inputs': serialize_shares(y_shares[k-1])} host, port = v tasks.append(talk_to_single_server(msg, host, port)) vals = [] for res in asyncio.as_completed(tasks, timeout=CLIENT_TIMEOUT): msg = await res if msg != None: vals.append(deserialize_shares(msg['result'])) if len(vals) > self.t: break return Shamir(self.t, self.n).reconstruct_bitstring_secret(vals)
def test_unnormalized_example(): t = 1 n = 3 c_path = "bristol_circuits/unnormalized_subregion_100_10.txt" n_triples = 200000 ones = ['1' for _ in range(1200)] inputs = Shamir(t, n).share_bitstring_secret(ones) for i in range(len(inputs)): inputs[i] = [0 for _ in range(64)] + inputs[i] result = bin(300)[2:] while len(result) < 64: result = '0' + result result = result * 10 test_mpc(t, n, c_path, n_triples, inputs, result)
def test_secure_addition(): t = 2 n = 2*t+1 shamir = Shamir(t, n) s1 = randelement() s2 = randelement() answer = s1+s2 shares1 = shamir.share_secret(s1) shares2 = shamir.share_secret(s2) # Each party locally adds their share of secret 1 and 2 final_shares = [shares1[i]+shares2[i] for i in range(n)] # Check reconstructed = shamir.reconstruct_secret(final_shares[0:t+1]) assert answer == reconstructed, "reconstructed the wrong value"
def test_extract_keys(): k = 7 secret = 113 amount_of_keys = 30 shamir = Shamir(k, secret) keys = [shamir.get_key() for _ in range(amount_of_keys)] for n in range(1, amount_of_keys + 1): key_subset = keys[:n] extracted_secret = Shamir.extract_secret(key_subset) if n < k: # Can get secret... but let's assert anyway assert extracted_secret != secret else: assert extracted_secret == secret
def _testShamirRecover(self, minimum, shares, prime, secret, keys): if self.debug >= 100: print( "testShamirRecover(minimum=%d,shares=%d,prime=%d,secret=%s,keys=%s)" % (minimum, shares, prime, secret, keys)) shamir = Shamir(minimum, prime) choices = list(range(shares)) for k in range(minimum): i = self.rng.next(len(choices)) shamir.setKey(choices[i] + 1, keys[choices[i]]) del choices[i] assert shamir.getSecret() == secret for i in range(shares): assert shamir.getKey(i + 1) == keys[i]
def test_add64_circuit(): t = 2 n = 5 c_path = "bristol_circuits/add64.txt" n_triples = 500 for x, y in [(100, 200), (2**30, 2**10), (2**64 - 1, 2**64 - 1)]: result = bin((x + y) % (2**64))[2:] x_bin = bin(x)[2:] while len(x_bin) < 64: x_bin = '0' + x_bin y_bin = bin(y)[2:] while len(y_bin) < 64: y_bin = '0' + y_bin inputs = Shamir(t, n).share_bitstring_secret(x_bin[::-1] + y_bin[::-1]) test_mpc(t, n, c_path, n_triples, inputs, result)
def test_mul64_circuit(): t = 2 n = 5 c_path = "bristol_circuits/mul64.txt" n_triples = 10000 for x, y in [(111, 2025), (2**64 - 1, 2**64 - 1)]: result = bin((x * y))[2:] x_bin = bin(x)[2:] while len(x_bin) < 64: x_bin = '0' + x_bin y_bin = bin(y)[2:] while len(y_bin) < 64: y_bin = '0' + y_bin inputs = Shamir(t, n).share_bitstring_secret(x_bin[::-1] + y_bin[::-1]) test_mpc(t, n, c_path, n_triples, inputs, result, reflect=True)
def test_lessthan32_circuit(): t = 2 n = 5 c_path = "bristol_circuits/lessthan32.txt" n_triples = 10000 for x, y in [(111, 2025), (2025, 111), (2**32 - 1, 2**32 - 1)]: result = bin(x < y)[2:] x_bin = bin(x)[2:] while len(x_bin) < 32: x_bin = '0' + x_bin y_bin = bin(y)[2:] while len(y_bin) < 32: y_bin = '0' + y_bin inputs = Shamir(t, n).share_bitstring_secret(x_bin[::-1] + y_bin[::-1]) test_mpc(t, n, c_path, n_triples, inputs, result)
def test_sub64_circuit(): t = 2 n = 5 c_path = "bristol_circuits/sub64.txt" n_triples = 500 for x, y in [(1000, 2010), (2025, 111), (2**64 - 2, 2**64 - 2)]: result = (x - y) % (2**64) result = bin(result)[2:] x_bin = bin(x)[2:] while len(x_bin) < 64: x_bin = '0' + x_bin y_bin = bin(y)[2:] while len(y_bin) < 64: y_bin = '0' + y_bin inputs = Shamir(t, n).share_bitstring_secret(x_bin[::-1] + y_bin[::-1]) test_mpc(t, n, c_path, n_triples, inputs, result)
def shamir_test(l, m, n): s = Shamir('english') seed = "Shamir's Secret Sharing Scheme!"[:l] # take first l characters shares = s.split(seed, m, n) print('original:', seed) print('shares:') for i in range(len(shares)): print('%2d :' % (i + 1), shares[i]) shares = shares[:m] # take first m shares cmb = s.combine(shares) print('combined:', cmb) if seed == cmb: print('TEST OK') print() else: print('TEST FAILED !!!') sys.exit(1)
def test_secure_multiplication(): t = 2 n = 2 * t + 1 n_muls = 5 shamir = Shamir(t, n) xs = [randelement() for _ in range(n_muls)] ys = [randelement() for _ in range(n_muls)] answers = [xs[i] * ys[i] for i in range(n_muls)] x_sharings = [shamir.share_secret(xs[i]) for i in range(n_muls)] y_sharings = [shamir.share_secret(ys[i]) for i in range(n_muls)] triples = test_triple_creation(t, n, n_muls) ## ## ROUND 1 ## broadcasts = [] # Each party for i in range(n): # computes intermediate values (er_list) for shares to be multiplied er_list = shamir.mul_gates_round_1([x[i] for x in x_sharings], [y[i] for y in y_sharings], triples[i]) # broadcasts the intermediate values to all other parties broadcasts.append(er_list) ## ## ROUND 2 ## player_result_shares = [] # Each party for i in range(n): # Collects broadcasted messages and uses these intermediate values to compute result shares result_shares = shamir.mul_gates_round_2([x[i] for x in x_sharings], [y[i] for y in y_sharings], broadcasts, [t.c for t in triples[i]]) player_result_shares.append(result_shares) # Check values for i in range(len(answers)): reconstructed = shamir.reconstruct_secret( [p[i] for p in player_result_shares]) assert reconstructed == answers[i], "reconstructed the wrong value"
def __init__(self, numshares, threshold): self.splitter = Shamir(numshares, threshold) self.numshares = numshares self.threshold = threshold
def _getShamir(self): shamir = Shamir(self.getMinimum(), self.getPrime()) for i in self._keys: shamir.setKey(i, self._keys[i]) return shamir
def run_triplegen_process(t, n, index, queues, main_queue, batch_size, n_batches): shamir = Shamir(t, n) messenger = MockMessenger(t, n, index, queues) tg = TripleGeneration(index, shamir, messenger, batch_size=batch_size, n_batches=n_batches) tg.run() main_queue.put(tg.triples)