async def sign(self, M): """Threshold Schnorr signature generation.""" g = self.group.generator H = self.H x = self.x secgrp = mpc.SecGrp(self.group) secfld = mpc.SecFld(self.group.order) u = mpc._random(secfld) a = await secgrp.repeat_public(g, u) # a = g^u c = H(a, M) r = u + c * x r = int(await mpc.output(r)) S = c, r return S
async def keygen(g): """Threshold ElGamal key generation.""" group = type(g) secgrp = mpc.SecGrp(group) n = group.order if n is not None and is_prime(n): secnum = mpc.SecFld(n) else: l = isqrt(-group.discriminant).bit_length() secnum = mpc.SecInt(l) while True: x = mpc._random(secnum) h = await secgrp.repeat_public(g, x) # g^x if h != group.identity: # NB: this branch will always be followed unless n is artificially small return x, h
async def bsgn_0(a): """Compute binary sign of a securely. Binary sign of a (1 if a>=0 else -1) is obtained by securely computing (2a+1 | p). Legendre symbols (a | p) for secret a are computed securely by evaluating (a s r^2 | p) in the clear for secret random sign s and secret random r modulo p, and outputting secret s * (a s r^2 | p). """ stype = type(a) await mpc.returnType(stype) Zp = stype.field p = Zp.modulus legendre_p = lambda a: gmpy2.legendre(a.value, p) s = mpc.random_bits(Zp, 1, signed=True) # random sign r = mpc._random(Zp) r = mpc.prod([r, r]) # random square modulo p a, s, r = await mpc.gather(a, s, r) b = await mpc.prod([2 * a + 1, s[0], r]) b = await mpc.output(b) return s[0] * legendre_p(b)
async def sign(self, M): """Threshold DSA signature generation.""" g = self.group.generator q = self.group.order H = self.H x = self.x secgrp = mpc.SecGrp(self.group) secfld = mpc.SecFld(q) while True: k = mpc._random(secfld) a = await secgrp.repeat_public(g, k) # a = g^k if a == self.group.identity: continue r = self.to_int(a) % q if r == 0: continue s = (H(M) + x * r) / k s = int(await mpc.output(s)) if s != 0: break S = r, s return S