def compute_proof_of_correctness(n, v, x, delta, s_i, v_i, x_i, protocol): x_tilde = protocol.calculate_x_tilde(x) r = randint(0, pow(2, n.bit_length() + (2 * L_1) - 1)) v_prime = powmod(v, r, n) x_prime = powmod(x_tilde, r, n) c = H_prime(v=v, x_tilde=x_tilde, v_i=v_i, x_i2=powmod(x_i, 2, n), v_prime=v_prime, x_prime=x_prime) z = s_i * c + r return (z, c)
def verify_poc(protocol, x, vks, i, poc_i, v, x_i, n): x_tilde = protocol.calculate_x_tilde(x) v_i = vks[i-1] z, c = poc_i vp1 = powmod(v, z, n) vp2 = powmod(v_i, -c, n) xp1 = powmod(x_tilde, z, n) xp2 = powmod(x_i, -2 * c, n) new_v_prime = (vp1 * vp2) % n new_x_prime = (xp1 * xp2) % n verification = H_prime(v=v, x_tilde=x_tilde, v_i=v_i, x_i2=powmod(x_i, 2, n), v_prime=new_v_prime, x_prime=new_x_prime) assert verification == c, "proof of correctness could not be verified"
def calculate_x_tilde(self, x): return powmod(x, 4, self.n)
def calculate_share(self, x, si): return powmod(x, 2 * si, self.n)
def calculate_x_tilde(self, x): return powmod(x, 4 * self.delta, self.n)
def main(args=None): assert version_info.major == 3 and version_info.minor == 8, "Ensure python version (= 3.8)" """ SETUP """ if args is None: args = parse_args() global loglevel loglevel = LogLevel[args.log] l, k, t = args.l, args.k, args.t log(f"Participating players: {l}, Number of collaborating players (Quorom size): {k}, Maximum number of corrupt players: {t}") assert l >= t + \ k, ("total number of participating players has to be larger than number of collaborating players and corrupt players combined") assert k >= t + \ 1, ("the minimum requried number of collaborating parties has to be at least one larger than the maximum number of corrupt parties") primegen_method = args.primegen log(f"Prime generation method: {primegen_method}") """ THE DEALER Generates safe primes for the public key modulus. Deals secret key shares and verification key shares. """ bitlength = args.bitlength log(f"Bitlength of primes: {bitlength}") # the fourth Fermat number - basically just a large number known to be prime e = pow(2, pow(2, 4)) + 1 assert e > l, "e has to be a prime larger than number of players" players = [Player() for _ in range(l)] dealer = Dealer(bitlength, e, primegen_method) # Shared values n, e = dealer.public_key v, u, m = dealer.v, dealer.u, dealer.m log(f"Bitlength of modulus: {n.bit_length()}") message = args.message log(f"message: {message}", LogLevel.VERBOSE) delta = factorial(l) protocol = None if k == t + 1: log("Protocol 1") protocol = Protocol1(message=message, n=n, delta=delta, m=m) else: # k > t + 1: log("Protocol 2") protocol = Protocol2(message=message, n=n, delta=delta, m=m, u=u, e=e) vks = dealer.deal(players, k, protocol) # Dealer is no longer used del dealer # Hashed message x = protocol.get_hashed_message() log(f"hashed message: {x}", LogLevel.VERBOSE) """ COMBINING SHARES Combines signature shares to get a signature. We simulate that we receive generated signature shares from k players. """ from random import sample S = sample(range(1, l + 1), k) log(f"Combining shares of players {S}", LogLevel.VERBOSE) w = 1 for i in S: x_i, poc_i = players[i-1].generate_signature_share(delta, protocol) # verify proof of correctness verify_poc(protocol, x, vks, i, poc_i, v, x_i, n) # combine signature share lambda_S_0i = lambda_(delta, 0, i, S) temp = powmod(x_i, 2 * lambda_S_0i, n) w = (w * temp) % n log(f"w: {w}", LogLevel.VERBOSE) e_prime = protocol.calculate_e_prime() gcd, a, b = xgcd(e_prime, e) assert gcd == 1, "gcd(e', e) != 1" xe_prime = powmod(x, e_prime, n) we = powmod(w, e, n) assert we == xe_prime, "w^e != x^e'" assert e_prime * a + e * b == 1, "e'a + eb != 1" wa = powmod(w, a, n) xb = powmod(x, b, n) y = protocol.calculate_y(wa, xb) ye = powmod(y, e, n) log(f"y^e: {ye}", LogLevel.VERBOSE) assert ye == H(message, n), "Invalid message signature" log("Message signature was valid!", LogLevel.DEFAULT)