def aggregate_pub_keys(public_keys, secure): """ Aggregates public keys together """ if len(public_keys) < 1: raise Exception("Invalid number of keys") public_keys.sort() computed_Ts = hash_pks(len(public_keys), public_keys) ec = public_keys[0].value.ec sum_keys = JacobianPoint(Fq.one(ec.q), Fq.one(ec.q), Fq.zero(ec.q), True, ec) for i in range(len(public_keys)): addend = public_keys[i].value if secure: addend *= computed_Ts[i] sum_keys += addend return PublicKey.from_g1(sum_keys)
def test_threshold_instance(T, N): commitments = [] # fragments[i][j] = fragment held by player i, # received from player j fragments = [[None] * N for _ in range(N)] secrets = [] # Step 1 : PrivateKey.new_threshold for player in range(N): secret_key, commi, frags = PrivateKey.new_threshold(T, N) for target, frag in enumerate(frags): fragments[target][player] = frag commitments.append(commi) secrets.append(secret_key) # Step 2 : Threshold.verify_secret_fragment for player_source in range(1, N + 1): for player_target in range(1, N + 1): assert Threshold.verify_secret_fragment( T, fragments[player_target - 1][player_source - 1], player_target, commitments[player_source - 1]) # Step 3 : master_pubkey = PublicKey.aggregate(...) # secret_share = PrivateKey.aggregate(...) master_pubkey = PublicKey.aggregate( [PublicKey.from_g1(cpoly[0].to_jacobian()) for cpoly in commitments], False) secret_shares = [ PrivateKey.aggregate(map(PrivateKey, row), None, False) for row in fragments ] master_privkey = PrivateKey.aggregate(secrets, None, False) msg = 'Test' signature_actual = master_privkey.sign(msg) # Step 4 : sig_share = secret_share.sign_threshold(...) # Check every combination of T players for X in combinations(range(1, N + 1), T): # X: a list of T indices like [1, 2, 5] # Check underlying secret key is correct r = Threshold.interpolate_at_zero( X, [secret_shares[x - 1].value for x in X]) secret_cand = PrivateKey(r) assert secret_cand == master_privkey # Check signatures signature_shares = [ secret_shares[x - 1].sign_threshold(msg, x, X) for x in X ] signature_cand = Signature.aggregate_sigs_simple(signature_shares) assert signature_cand == signature_actual # Check that the signature actually verifies the message agg_info = AggregationInfo.from_msg(master_pubkey, msg) signature_actual.set_aggregation_info(agg_info) assert signature_actual.verify() # Step 4b : Alternatively, we can add the lagrange coefficients # to 'unit' signatures. for X in combinations(range(1, N + 1), T): # X: a list of T indices like [1, 2, 5] # Check signatures signature_shares = [secret_shares[x - 1].sign(msg) for x in X] signature_cand = Threshold.aggregate_unit_sigs(signature_shares, X, T) assert signature_cand == signature_actual